我在 Django 中以附件形式发送请求时遇到问题。我的应用程序将一些数据写入文件并将其压缩。但是,当我返回附件响应时,浏览器会下载它,但 zip 文件已损坏。 (原始 zip 包含我的文件,没有给出任何错误。)
我的代码在这里:
file_path = "/root/Programs/media/statics/schedules/"
zip_file_name = file_path + "test.zip"
zip_file = zipfile.ZipFile(zip_file_name, "w")
for i in range(len(planner_list)):
file_name = file_path + str(planner_list[i][0].start_date)
render_to_file('deneme.html',file_name ,{'schedule':schedule})
zip_file.write(file_name, os.path.basename(file_name),zipfile.ZIP_DEFLATED)
os.remove(file_name)
zip_file.close()
response = HttpResponse(file_path , content_type='application/zip')
response['Content-Disposition'] = 'attachment; filename=test.zip'
return response
请您参考如下方法:
HttpResponse 接受一个字符串或一个返回字符串的迭代器(就像一个打开的类文件对象)。您将文件路径传递给它,因此响应包含一个文件,其内容只是文件路径,而不是您写入文件的有效 zip 内容。您可以只使用 open 作为 HTTPResponse 对象将为您关闭文件:
response = HttpResponse(open(file_path, 'rb'), content_type='application/zip')
引用文档:
Finally, you can pass HttpResponse an iterator rather than strings. HttpResponse will consume the iterator immediately, store its content as a string, and discard it. Objects with a close() method such as files and generators are immediately closed.
If you need the response to be streamed from the iterator to the client, you must use the StreamingHttpResponse class instead.
在每个请求上写入磁盘可能会损害您的服务器 I/O - 查看您的代码,一切似乎都小到足以容纳内存。您可以使用 (C)StringIO(Python3 中的 BytesIO)代替真实文件:
from io import BytesIO
mem_file = BytesIO()
with zipfile.ZipFile(mem_file, "w") as zip_file:
for i, planner in enumerate(planner_list):
file_name = str(planner[0].start_date)
content = render_to_string('deneme.html', {'schedule':schedule})
zip_file.writestr(file_name, content)
f.seek(0) # rewind file pointer just in case
response = HttpResponse(f, content_type='application/zip')
