【问题标题】:Python: How to download file using range of bytes?Python:如何使用字节范围下载文件?
【发布时间】:2014-03-13 14:34:54
【问题描述】:

我想以多线程模式下载文件,这里有以下代码:

#!/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)?

【问题讨论】:

  • 这可能会有所帮助:stackoverflow.com/q/8293687/2319400
  • 见这里:stackoverflow.com/questions/1798879/… 不同的库,但应该让你走上正轨。
  • @sebastian 谢谢你的评论。我已经看到了这个答案。此外,我使用wireshark捕获数据包。然而,目前尚不清楚如何检测服务器是否支持范围选择。我的意思是有办法检查文件是否可以使用范围选择下载?有些应用程序支持通过范围选择进行多线程下载,但是如果服务器不支持,它仍然会尝试在其他线程中下载文件(即 flashgot、reget 等)。但是,我如何获取服务器或文件信息,我可以在其中查找范围支持信息?
  • @pi。感谢您的评论。如果httplib 没有提供的功能还不够,我会毫不犹豫地使用支持它的库。

标签: python python-2.7 http-headers http-protocols


【解决方案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_offsetend_offset 都包含在内。

更新

如果服务器不理解 Range 标头,它会以状态码 200 (httplib.OK) 而不是 206 (httplib.PARTIAL_CONTENT) 进行响应,并将发送整个内容。为确保服务器响应部分内容,请检查状态码。

>>> resp.status == httplib.PARTIAL_CONTENT
True

【讨论】:

  • 感谢您的回答。我真的很感谢你的快速反应。我会接受你的回答。还有一件事是可以检测服务器是否支持或不支持下载范围选择?
  • @Phoenix,如果服务器不支持 Range 标头,它将以 200 (httplib.OK) 状态码而不是 206 (httplib.PARTIAL_CONTENT) 响应。所以检查状态码如示例代码所示:resp.status == httplib.PARTIAL_CONTENT
  • 感谢您的澄清,因为您今天达到了每日限额,我明天将投票赞成您的回答。 :)
  • 如果您可以通过一点解释来扩展您的答案,这将有助于其他不阅读 cmets 的人。谢谢。
  • @Phoenix,我认为答案中的&gt;&gt;&gt; resp.status == httplib.PARTIAL_CONTENT 就足够了。我按照您的建议用解释更新了答案。感谢您的评论。
猜你喜欢
  • 2018-02-14
  • 2015-11-05
  • 1970-01-01
  • 2021-12-24
  • 2022-11-30
  • 1970-01-01
  • 2022-11-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多