Скачать файл с помощью частичной загрузки (HTTP)

Есть ли способ загрузить огромный и все еще растущий файл через HTTP с помощью функции частичной загрузки?

Кажется, что этот код загружает файл с нуля каждый раз, когда он выполняется:

import urllib
urllib.urlretrieve ("http://www.example.com/huge-growing-file", "huge-growing-file")

Мне бы хотелось:

  • Чтобы получить только недавно записанные данные
  • Загрузите с нуля только в том случае, если исходный файл станет меньше (например, он был повернут).

Ответ 1

Можно выполнить частичную загрузку с использованием заголовка диапазона, следующее запросит выбранный диапазон байтов:

req = urllib2.Request('http://www.python.org/')
req.headers['Range'] = 'bytes=%s-%s' % (start, end)
f = urllib2.urlopen(req)

Например:

>>> req = urllib2.Request('http://www.python.org/')
>>> req.headers['Range'] = 'bytes=%s-%s' % (100, 150)
>>> f = urllib2.urlopen(req)
>>> f.read()
'l1-transitional.dtd">\n\n\n<html xmlns="http://www.w3.'

Используя этот заголовок, вы можете возобновить частичную загрузку. В вашем случае все, что вам нужно сделать, это отслеживать уже загруженный размер и запрашивать новый диапазон.

Имейте в виду, что сервер должен принять этот заголовок, чтобы это работало.

Ответ 2

Это довольно просто сделать, используя сокеты TCP и raw HTTP. Соответствующим заголовком запроса является "Диапазон".

Пример запроса может выглядеть так:

mysock = connect(("www.example.com", 80))
mysock.write(
  "GET /huge-growing-file HTTP/1.1\r\n"+\
  "Host: www.example.com\r\n"+\
  "Range: bytes=XXXX-\r\n"+\
  "Connection: close\r\n\r\n")

Где XXXX представляет количество байтов, которые вы уже получили. Затем вы можете прочитать заголовки ответов и любой контент с сервера. Если сервер возвращает заголовок, например:

Content-Length: 0

Вы знаете, что у вас есть весь файл.

Если вы хотите быть особенно приятным в качестве HTTP-клиента, вы можете посмотреть в "Connection: keep-alive". Возможно, есть библиотека python, которая делает все, что я описал (возможно, даже urllib2 делает это!), Но я не знаком с ним.

Ответ 3

Если я правильно понимаю ваш вопрос, файл не меняется во время загрузки, но регулярно обновляется. Если это вопрос, rsync является ответом.

Если файл постоянно обновляется во время загрузки, вам необходимо изменить rsync или программу bittorrent. Они разбивают файлы на отдельные куски и загружают или обновляют куски самостоятельно. Когда вы дойдете до конца файла с первой итерации, повторите, чтобы получить добавленный кусок; по мере необходимости. С меньшей эффективностью можно было бы просто повторно rsync.