将来自响应的zip文件添加到Django的FileField中。

14 浏览
0 Comments

将来自响应的zip文件添加到Django的FileField中。

目前我正在调用一个API,它会返回一个zip文件。当使用requests库时,\n

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

\n我可以得到一个成功的响应,其中包含以字符串形式返回的zip文件。\n当我检查res.contents的内容时,我得到的是:\n

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

\n看起来它返回的是一个字符串形式的zip文件。我参考了这个问题here,试图将这个字符串转换回原始的zip文件。具体来说,我写了以下代码:\n

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

\n在尝试保存时,我得到了以下错误:\n

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

\n我的最终目标是将这个zip文件绑定到一个UploadedFile类上:\n

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

\n如果我使用HTML表单来访问这个API,请求成功后我的浏览器会自动下载这个zip文件。有没有办法解决这个问题?

0
0 Comments

问题的原因是作者试图将从API响应中获取的zip文件添加到Django的FileField中,但是作者使用了错误的方法和对象来实现这一目标。

解决方法是使用SimpleUploadedFile对象将API响应的内容转换为可用于Django的文件,并将其保存到FileField中。另外,还提供了使用File(BytesIO(res.content))ContentFile的替代方法。

以下是解决方法的代码示例:

from django.core.files.uploadedfile import SimpleUploadedFile
from django.core.files.base import File
from django.core.files.base import ContentFile
from io import BytesIO
import zipfile
# res.content is the bytes of your API response
res = request.post('http://url/to/api', files={'file_pro': *myfile*})
# Option 1: Using SimpleUploadedFile
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())
# Option 2: Using File(BytesIO())
my_file = File(BytesIO(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())
# Option 3: Using ContentFile
my_file = ContentFile(res.content, 'temp.zip')
# 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中内置了一个模型。

SimpleUploadedFile是Django中File的子类,其实现使用了Python的BytesIO。如果不想使用SimpleUploadedFile,可以通过File(BytesIO(res.content))实现相同的效果。

作者尝试使用ContentFile,也得到了成功的结果。

0