我可以获得content-encoding
为gzip
的文件。
这是否意味着服务器将其存储为压缩文件,或者对于存储为压缩zip或7z文件的文件也是如此?
如果是这样(其中durl
是一个zip文件)
>>> durl = 'https://db.tt/Kq0byWzW'
>>> dresp = requests.get(durl, allow_redirects=True, stream=True)
>>> dresp.headers['content-encoding']
'gzip'
>>> r = requests.get(durl, stream=True)
>>> data = r.raw.read(decode_content=True)
但数据出来是空的,而我想在旅途中将zip文件解压缩到磁盘上!
答案 0 :(得分:0)
您需要来自请求文件的内容才能编写它。 确认工作:
import requests
durl = 'https://db.tt/Kq0byWzW'
dresp = requests.get(durl, allow_redirects=True, stream=True)
dresp.headers['content-encoding']
file = open('test.html', 'w')
file.write(dresp.text)
答案 1 :(得分:0)
首先,durl
不是zip文件,而是一个dropbox登录页面。所以你要看的是使用gzip编码发送的HTML。如果您使用gzip从原始套接字解码数据的位置,您只需获取HTML。因此,使用raw实际上只是隐藏了你不小心去了另一个文件而不是你想到的文件。
根据您要求的https://plus.google.com/u/0/100262946444188999467/posts/VsxftxQnRam
有没有人知道将压缩文件直接写入磁盘到解压缩状态?
我认为你真的想要获取一个zip并将其直接解压缩到一个目录而不先存储它。为此,您需要使用https://docs.python.org/2/library/zipfile.html
虽然在这一点上问题变成了请求的响应实际上是不可寻的,但是zipfile需要哪个才能工作(它将要做的第一件事就是寻找文件的末尾以确定它有多长是)。
要解决此问题,您需要将响应包装在像object这样的文件中。我个人建议使用tempfile.SpooledTemporaryFile
设置最大尺寸。这样,如果文件大于您的预期,您的代码将切换到将内容写入磁盘。
import requests
import tempfile
import zipfile
KB = 1<<10
MB = 1<<20
url = '...' # Set url to the download link.
resp = requests.get(url, stream=True)
with tmp as tempfile.SpooledTemporaryFile(max_size=500*MB):
for chunk in resp.iter_content(4*KB):
tmp.write(chunk)
archive = zipfile.ZipFile(tmp)
archive.extractall(path)
使用io.BytesIO
的相同代码:
resp = requests.get(url, stream=True)
tmp = io.BytesIO()
for chunk in resp.iter_content(4*KB):
tmp.write(chunk)
archive = zipfile.ZipFile(tmp)
archive.extractall(path)
答案 2 :(得分:0)
您必须区分content-encoding(不要与transfer-encoding混淆)和content-type。
它的要点是content-type
是您尝试获取的资源的媒体类型(真实文件类型)。 content-encoding
是在将其发送给客户端之前应用于它的任何修改。
因此,我们假设您想获得名为“foo.txt”的资源。它可能具有text/plain
的内容类型。在添加中,可以通过网络发送时修改数据。这是content-encoding
。因此,通过上面的示例,您可以拥有text/plain
的内容类型和content-encoding
的{{1}}。这意味着在服务器将文件发送到线路之前,它将使用gzip
动态压缩它。所以遍历网络的唯一字节是压缩的。不是原始文件的原始字节(gzip
)。
客户端的工作就是相应地处理这些标题。
现在,我不是100%确定foo.txt
,或者底层python库这样做但是他们很可能会这样做。如果没有,Python附带一个默认的gzip library,所以你可以自己做,没有问题。
考虑到上述情况,回答您的问题:不,拥有requests
的“内容编码”并不意味着远程资源是zip文件。包含该信息的字段为gzip
(根据您的问题,根据使用的实际压缩算法,其值可能为content-type
或application/zip
。
如果您无法根据application/x-7z-compressed
字段(f.ex.,如果它是content-type
)确定真实文件类型,则可以将文件保存到磁盘,然后打开十六进制编辑器。对于application/octet-stream
文件,您应该在某处看到字节序列7z
。最有可能在文件的开头或EOF-112字节。如果是37 7a bc af 27 1c
文件,则文件开头应为gzip
。
鉴于您在1f 8b
字段中有gzip
:如果您收到content-encoding
个文件,则可以确定7z
已解析requests
并且为你妥善解码。如果你得到一个content-encoding
文件,那可能意味着两件事。 gzip
未解码任何内容,文件确实是requests
文件,因为它可能是使用gzip
编码发送的gzip
文件。这意味着它会被双重压缩。这没有任何意义,但是,取决于服务器,这仍然可能发生。
您可以尝试在控制台上运行gzip
,看看你得到了什么。