Возобновляемая загрузка файлов в python
Я пытаюсь загрузить файл в python, и я хочу загрузить файл в возобновляемом режиме, т.е. когда возобновляется подключение к Интернету, возобновляется загрузка файла с предыдущего этапа.
Есть ли какой-то конкретный протокол, который поддерживает возобновляемую загрузку файлов.
заранее спасибо
2 ответа
Поэтому вам нужно найти файл и отправить команду REST, чтобы сообщить серверу о загрузке из нужного места.
Вот код, который будет пытаться до тех пор, пока он не завершит загрузку с резюме, также включена отладка, чтобы вы могли следовать:
#!/usr/bin/env python3
import ftplib
import os
import sys
import time
import socket
class FtpUploadTracker:
sizeWritten = 0
totalSize = 0.0
lastShownPercent = 0
def __init__(self, totalSize):
self.totalSize = totalSize
def handle(self, block):
self.sizeWritten += 1024
percentComplete = round((self.sizeWritten / self.totalSize) * 100)
if (self.lastShownPercent != percentComplete):
self.lastShownPercent = percentComplete
print(str(percentComplete) + "% complete ramaing: " + str(self.totalSize - self.sizeWritten), flush=True)
if __name__ == "__main__":
Server="servername.com"
Username="username"
Password="secret password"
filename = "/path/to/folder"
Directory="/path/on/server"
tries = 0
done = False
print("Uploading " + str(filename) + " to " + str(Directory), flush=True)
while tries < 50 and not done:
try:
tries += 1
with ftplib.FTP(Server) as ftp:
ftp.set_debuglevel(2)
print("login", flush=True)
ftp.login(Username, Password)
# ftp.set_pasv(False)
ftp.cwd(Directory)
with open(filename, 'rb') as f:
totalSize = os.path.getsize(filename)
print('Total file size : ' + str(round(totalSize / 1024 / 1024 ,1)) + ' Mb', flush=True)
uploadTracker = FtpUploadTracker(int(totalSize))
# Get file size if exists
files_list = ftp.nlst()
print(files_list, flush=True)
if os.path.basename(filename) in files_list:
print("Resuming", flush=True)
ftp.voidcmd('TYPE I')
rest_pos = ftp.size(os.path.basename(filename))
f.seek(rest_pos, 0)
print("seek to " + str(rest_pos))
uploadTracker.sizeWritten = rest_pos
print(ftp.storbinary('STOR ' + os.path.basename(filename), f, blocksize=1024, callback=uploadTracker.handle, rest=rest_pos), flush=True)
else:
print(ftp.storbinary('STOR ' + os.path.basename(filename), f, 1024, uploadTracker.handle), flush=True)
done = True
except (BrokenPipeError, ftplib.error_temp, socket.gaierror) as e:
print(str(type(e)) + ": " + str(e))
print("connection died, trying again")
time.sleep(30)
print("Done")
Волшебная линия:
print(ftp.storbinary('STOR ' + os.path.basename(filename), f, blocksize=1024, callback=uploadTracker.handle, rest=rest_pos), flush=True)
У которого есть rest=rest_pos
,
Если задан необязательный отдых, команда REST отправляется на сервер, передавая rest в качестве аргумента. rest - это обычно смещение байта в запрошенном файле, указывающее серверу перезапустить передачу байтов файла с запрошенным смещением, пропуская начальные байты. Однако обратите внимание, что RFC 959 требует только, чтобы rest был строкой, содержащей символы в печатаемом диапазоне от ASCII-кода 33 до ASCII-кода 126. Поэтому метод Transfercmd() конвертирует rest в строку, но проверка содержимого строки не выполняется., Если сервер не распознает команду REST, будет сгенерировано исключение error_reply. Если это произойдет, просто вызовите Transfercmd() без аргумента rest
Источник
Также некоторый код взят здесь
Отличный ответ от GuySoft - мне очень помогло. Мне пришлось немного изменить его, поскольку я никогда (пока) не сталкивался с тремя исключениями, которые улавливает его сценарий, но я испытал много ошибок ConnectionResetError и socket.timeout при загрузке по FTP, поэтому я добавил это. Я также заметил, что если я добавил тайм-аут 60 секунд при входе в систему по ftp, количество ConnectionResetErrors значительно уменьшилось (но не все вместе). Часто происходило то, что загрузка зависала на 100% на ftp.storbinary до socket.timeout, затем пыталась 49 раз и выходила. Я исправил это, сравнив totalSize и rest_pos, и вышел при равенстве. Итак, у меня есть рабочее решение, но я попытаюсь выяснить, что вызывает тайм-ауты сокета. Интересно то, что когда я использовал Filezilla и даже скрипт PHP, загрузка файлов на один и тот же FTP-сервер работала без сбоев.