【问题标题】:download a file properly with python if no Content-Length is provided如果没有提供 Content-Length,则使用 python 正确下载文件
【发布时间】:2011-10-05 13:46:26
【问题描述】:

如果 http 响应不包含 Content-Length 标头,我如何使用 python 正确下载文件?

我在 appengine 的 send_blob() 函数中遇到了这个问题,由于某种原因,它不会在更大 (20mb+) 的 blob 上添加 Content-Length 标头。

现在我正在使用 urllib.urlretrieve() 但有时它不会下载整个文件。 我现在正在做的是在下载文件之前发送内容长度,这样我就可以在继续之前检查文件的大小是否正确。

我不确定是否有更好的方法来做到这一点。

其中一个文件的标题:

HTTP/1.1 200 OK
Cache-Control: no-cache
Content-Type: application/octet-stream
Expires: Fri, 01 Jan 1990 00:00:00 GMT
Date: Fri, 30 Sep 2011 19:41:34 GMT
Server: Google Frontend
Transfer-Encoding: Identity
Connection: close

我只是尝试使用 wget 下载带有wget --server-response --continue 的文件,并且标题是:

  HTTP/1.1 200 OK
  Cache-Control: no-cache
  Content-Type: application/octet-stream
  Expires: Fri, 01 Jan 1990 00:00:00 GMT
  Date: Wed, 05 Oct 2011 14:08:13 GMT
  Server: Google Frontend
  Transfer-Encoding: chunked
Length: unspecified [application/octet-stream]

【问题讨论】:

  • 关闭 HTTP 连接(从服务器端)是否有效? (不确定这是否会产生明确定义的行为,但这是我的最佳猜测)
  • 当它不发送Content-Length时,是使用Transfer-Encoding: chunked吗?
  • @ninjagecko:实际上不知道在使用 send_blob() 函数时是否可以手动关闭连接。
  • @SteveJessop:我通过添加与这些文件之一一起发送的标题来编辑问题。

标签: python google-app-engine download


【解决方案1】:

如果服务器没有给出请求数据长度的指示,向你发送一些数据然后关闭连接,那么 HTTP 客户端 必须假定所有数据都已成功传输。

只有使用额外的非 HTTP 信息,例如有效负载格式中的校验和或其他纠错,应用程序才能确定发生了错误,并使用HTTP Range header(即Range: bytes=NNNN-) 在随后的客户端请求中恢复传输。

如果服务器不支持Range 标头,如果服务器在任何时候传输响应标头Accept-Ranges: none,您可能会得出结论,那么据我所知,您对损坏的服务器实现没有追索权,除了定期重试请求,希望它最终提供通过错误检测的响应。

脚注:在提供 blob 内容时缺少 Content-Length 标头对我来说并不奇怪。许多数据库 API 不允许在不实际检索整个事物的情况下测试 blob 的长度。我怀疑造成这种情况的原因是 SQL 引擎本身缺乏对这个测试的支持。

【讨论】:

  • 只有在不使用分块编码时才会出现这种情况。
【解决方案2】:

App Engine 正在使用 chunked encoding 发送响应,这允许客户端确定响应何时完成。不过,urllib 应该为您处理这个问题;似乎您的连接可能由于某种原因而过早终止,而 urllib 没有将其传达给您(或者您正在捕获并忽略异常)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-15
    • 1970-01-01
    • 2014-06-05
    • 2010-10-20
    • 1970-01-01
    • 2011-01-22
    相关资源
    最近更新 更多