如果没有提供Content-Length,请使用python正确下载文件

时间:2011-10-05 13:46:26

标签: python google-app-engine download

如果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]

2 个答案:

答案 0 :(得分:1)

如果服务器未指示所请求数据的长度,向您发送一些数据然后关闭连接,则 HTTP客户端必须假定所有数据都已成功传输。< / p>

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

如果服务器不支持Range标头,如果服务器随时发送响应标头Accept-Ranges: none,您可以得出结论,那么据我所知,您无法对损坏的服务器进行追索实现,除了定期重试请求,希望它最终提供通过错误检测的响应。

脚注:在提供blob内容时,Content-Length标题丢失并不令我感到意外。许多数据库API不允许测试blob的长度而不实际检索整个事物。我怀疑这样做的原因是缺乏对SQL引擎本身测试的支持。

答案 1 :(得分:0)

App Engine使用chunked encoding发送响应,允许客户端确定响应何时完成。 urllib应该为你处理这个问题;由于某种原因,你的连接似乎很可能会提前终止,而urllib也没有与你沟通(或者你正在捕捉并忽略异常)。