我一直在使用SpiderOak的这个Zipstream模块,它基本上允许你流式传输和压缩文件或文件夹而无需向光盘写任何东西。它产生大量不规则大小的数据。
现在,我正在尝试将目录上传到文件托管网站,要求我在帖子请求中发送file
和apikey
字段。有了请求,我必须像这样为apikey构建一个dict:
data = {'apikey': 'myapikey'}
并将整个zipstream读入字符串并将其传递给文件编码字典:
files = {'file': ('mydir.zip', the_string_that_is_a_zipped_dir)}
然后发出请求
r = requests.post(url, data=data, files=files).
这没关系。但是我希望将来传输更大的东西,并且在内存中读取整个文件是一个不错的想法。 我在请求高级部分看到你可以发送一个生成器作为数据字段,但后来我无法发送api密钥并且必须手动修改标头以设置内容类型和所有这些东西,所以它不起作用。还试图从api键和zip文件生成器中形成一个字典,就像这样 data = { 'file':('mydir.zip',generator()), 'apikey':'myapikey' }
但是失败了(正如预期的那样)。
有没有办法破解请求使用生成器为多部分表单数据中的文件生成字符串?
答案 0 :(得分:0)
好的,经过一番努力,我设法让这个工作没有请求,而是使用模块poster。
首先我在zipstream周围创建了一个fileobject包装器,如下所示:
from zipstream import ZipStream
class Zipit:
def __init__( self, path):
self.it = iter(ZipStream(path,compression=0))
self.next_chunk = ""
self.length = -1
self.path = path
self.__is_zipit__=''
@property
def size(self):
if self.length < 0:
self.length = 0
zip_object = ZipStream(self.path,compression=0)
for data in zip_object:
self.length += len(data)
return self.length
def growChunk( self ):
self.next_chunk = self.next_chunk + self.it.next()
def read( self, n ):
if self.next_chunk == None:
return None
try:
while len(self.next_chunk)<n:
self.growChunk()
rv = self.next_chunk[:n]
self.next_chunk = self.next_chunk[n:]
return rv
except StopIteration:
rv = self.next_chunk
self.next_chunk = None
return rv
为了拥有一个简单的api(代码无耻地改编自SO上的另一个例子)。
然后根据海报的doc创建必要的多部分对象:
z = Zipit('/my/path/to/zip')
f = MultipartParam('file', fileobj=z, filesize=z.size, filename='test.zip',filetype='application/zip')
datagen, headers = multipart_encode([ f, ('akey', 'mykey')])
如果fileobject字段是Zipit实例,最后一个hack就是跳过重置:
def reset(self):
if hasattr(self.fileobj, '__is_zipit__'): return
if self.fileobj is not None:
self.fileobj.seek(0)
elif self.value is None:
raise ValueError("Don't know how to reset this parameter")
这对我有用。希望它能帮助你们五个人中的任何一个。