对象存储用的是minio,所以是先到minio中取到文件,然后读取,存在本地指定目录,然后再通过迭代器读取的方式去读取文件返回给前端(怕一次性读取太多造成服务器卡死)
直接上代码:
import zipfile
def file_iterator(file_path, chunk_size=512):
""" 文件读取迭代器
:param file_path:文件路径
:param chunk_size: 每次读取流大小
:return:
"""
with open(file_path, 'rb') as target_file:
while True:
chunk = target_file.read(chunk_size)
if chunk:
yield chunk
else:
break
# 指定打包后的文件存储路径
download_path = settings.DADI_DIR
file_path = download_path + 'compress.zip'
# 创建一个zip对象,第一个参数是路径,第二个参数w是写入的意思,有r/w/a三种模式,分别代表读、写、添加,默认为r,即读模式。
zipFile = zipfile.ZipFile(file_path , 'w')
# doc.Doc().get_object(i)方法是从minio里面获取文件的Response对象,以下是将多个文件写入压缩文件中
# 你也可以不用这样写,在后面的writestr方法第二个参数中直接传前端传过来的文件流二进制也行
for i in doc_list:
x = doc.Doc().get_object(i)
# writestr方法是将一个文件写入存档。第二个参数,它可以是'str'或'bytes'实例;如果它是“str”,它首先被编码为UTF-8。第一个参数要么是ZipInfo实例,要么是ZIP文件中的文件名
zipFile.writestr(x['name'], x['download_data'].read(), zipfile.ZIP_DEFLATED)
zipFile.close()
# FileResponse专门是用来处理二进制文件的
rep = FileResponse(file_iterator(file_path), content_type='APPLICATION/OCTET-STREAM')
# compress.zip 为返回的文件名
rep['Content-Disposition'] = "attachment; filename="+urlquote('compress.zip')
return rep
需要注意的是,如果是大文件的话,还是不建议直接返回,会受到http的请求体长度限制还有nginx里面也需要配置,建议采用返回链接的形式给前端,将文件存到对象存储服务器,然后调用对象存储服务器的SDK获得文件的下载链接,返回