首页 文章

从对Django FileField的响应中添加zip文件

提问于
浏览
1

目前我正在调用一个发送回zip文件的API . 使用 requests

res = requests.post('http://url/to/api', files={'file_pro': *my_file*})

我能够以返回的zip作为字符串获得成功的响应 . 当我检查我的res.contents的内容时,我得到:

PK\x03\x04\x14\x00\x00\x00\x08\x00\x0c\x83HH\xba\xd2\xf1\t\xa1\x00\x00\x00\x04\x01\x00\x00....05\x06\x00\x00\x00\x00\x08\x00\x08\x00\x1e\x02\x00\x00$\x04\x00\x00\x00\x00

看起来它将zip文件作为字符串返回 . 我查看了这个问题here以尝试将此字符串转换为原始zip文件 . 具体来说我写道:

my_file = UploadedFile(file=File(zipfile.ZipFile(StringIO.StringIO(res.content)),'r'))
my_file.save()

在尝试保存时,我收到以下错误:

KeyError: 'There is no item named 65536 in the archive'

我的最终目标是将此zip文件绑定到 UploadedFile

class UploadedFile(BaseModel):
  file = models.FileField(upload_to='/path', max_length=255)

如果我使用html表单来访问此API,我的浏览器会在请求成功后自动下载zip . 知道如何解决这个问题吗?

1 回答

  • 1

    requests 库允许您将响应作为二进制数据返回 - http://docs.python-requests.org/en/master/user/quickstart/#binary-response-content .

    您不需要使用 ZipFile 来重建zip,传回的数据应该已经是zip文件的字节 .

    from django.core.files.uploadedfile import SimpleUploadedFile
    
    # res.content is the bytes of your API response
    res = request.post('http://url/to/api', files={'file_pro': *myfile*})
    my_file = SimpleUploadedFile('temp.zip', res.content)
    
    # verify the zip file
    assert zipfile.is_zipfile(my_file)
    
    # finally save the file
    uploaded_file = UploadedFile(file=my_file)
    uploaded_file.save()
    
    # play around with the zipfile
    with zipfile.ZipFile(uploaded_file.file) as my_zip_file:
        print(my_zip_file.infolist())
    

    请注意 zipfile.ZipFile 采用文件名或类文件对象 . 在您的问题中,您直接将字符串/字节传递给它 .

    同时考虑重命名 UploadedFile 模型,因为Django已经在 django.core.files.uploadedfile.UploadedFile 内置了一个内置模型 .

相关问题