Python: Как скачать файл, используя диапазон байтов?

Я хочу скачать файл в многопоточном режиме, и у меня есть следующий код здесь:

#!/usr/bin/env python

import httplib


def main():
    url_opt = '/film/0d46e21795209bc18e9530133226cfc3/7f_Naruto.Uragannie.Hroniki.001.seriya.a1.20.06.13.mp4'

    headers = {}
    headers['Accept-Language'] = 'en-GB,en-US,en'
    headers['Accept-Encoding'] = 'gzip,deflate,sdch'
    headers['Accept-Charset'] = 'max-age=0'
    headers['Cache-Control'] = 'ISO-8859-1,utf-8,*'
    headers['Cache-Control'] = 'max-age=0'
    headers['User-Agent'] = 'Mozilla/5.0 (Windows NT 5.1)'
    headers['Connection'] = 'keep-alive'
    headers['Accept'] = 'text/html,application/xhtml+xml,application/xml,*/*'
    headers['Range'] = ''

    conn = httplib.HTTPConnection('data09-cdn.datalock.ru:80')
    conn.request("GET", url_opt, '', headers)

    print "Request sent"

    resp = conn.getresponse()
    print resp.status
    print resp.reason
    print resp.getheaders()

    file_for_wirte = open('cartoon.mp4', 'w')
    file_for_wirte.write(resp.read())

    print resp.read()

    conn.close()


if __name__ == "__main__":
    main()

Вот вывод:

Request sent
200
OK
[('content-length', '62515220'), ('accept-ranges', 'bytes'), ('server', 'nginx/1.2.7'), ('last-modified', 'Thu, 20 Jun 2013 12:10:43 GMT'), ('connection', 'keep-alive'), ('date', 'Fri, 14 Feb 2014 07:53:30 GMT'), ('content-type', 'video/mp4')]

Этот код работает отлично, однако я не понимаю в документации, как загрузить файл, используя диапазоны. Если вы видите вывод ответа, какой сервер предоставляет:

 ('content-length', '62515220'), ('accept-ranges', 'bytes')

Он поддерживает диапазон в байтах, где размер контента составляет 62515220.

Однако в этом запросе весь файл загружен. Но что я хочу сделать, чтобы сначала получить информацию о сервере, например, может ли этот файл поддерживаться с помощью запросов диапазона http и размера файла без загрузки? И как я могу создать HTTP-запрос с диапазоном (то есть: 0~25000)?

1 ответ

Решение

Проходить Range заголовок с bytes=start_offset-end_offset как спецификатор диапазона.

Например, следующий код извлекает первые 300 байтов. (0-299):

>>> import httplib
>>> conn = httplib.HTTPConnection('localhost')
>>> conn.request("GET", '/', headers={'Range': 'bytes=0-299'}) # <----
>>> resp = conn.getresponse()
>>> resp.status
206
>>> resp.status == httplib.PARTIAL_CONTENT
True
>>> resp.getheader('content-range')
'bytes 0-299/612'
>>> content = resp.read()
>>> len(content)
300

ПРИМЕЧАНИЕ Оба start_offset, end_offset включительно.

ОБНОВИТЬ

Если сервер не понимает Range заголовок, ответит кодом состояния 200 (httplib.OK) вместо 206 (httplib.PARTIAL_CONTENT), и он будет отправлять весь контент. Чтобы убедиться, что сервер отвечает частичным содержимым, проверьте код состояния.

>>> resp.status == httplib.PARTIAL_CONTENT
True
Другие вопросы по тегам