Flask+vue+axios实现流式zip包传输

1. Flask部分

1.1 创建压缩包

class DirPackage:

@staticmethod

def pack_zip(from_path, to_path):

"""打包指定路径到某目录下面

:param from_path: 打包路径

:param to_path: .zip结尾的文件存放位置

"""

z = zipfile.ZipFile(to_path, 'w', zipfile.ZIP_DEFLATED)

for path, dirnames, filenames in os.walk(from_path):

fpath = path.replace(from_path, '')

for filename in filenames:

encode_name = filename.encode('utf-8').decode('utf-8')

z.write(os.path.join(path, filename),

os.path.join(fpath, encode_name))

z.close()

(file_path, file_name) = os.path.split(to_path)

return file_name

1.2 封装流式传输部分

class DownloadService:

@staticmethod

def download_zip_file(saver: DownloadDirFactory, user_name: str, token: str, **kwargs):

zip_file = os.path.join(saver.NORMAL_0, '{}_{}.zip'.format(user_name, token))

file_name = DirPackage.pack_zip(saver.NORMAL_1, zip_file)

def send():

with open(zip_file, 'rb') as file:

while True:

data = file.read(20 * 1024 * 1024) # 20M

if not data:

break

yield data

response = Response(send(), content_type='application/octet-stream')

response.headers["Access-Control-Expose-Headers"] = "Content-Disposition"

response.headers["Content-Disposition"] = 'attachment; filename={}'.format(file_name.encode('utf-8').decode('ISO-8859-1'))

return response

response需要设置Access-Control-Expose-Headers否则前台axios,post请求无法获取对应的文件名

1.3 路由接口

@staticmethod

@app.route("/app/multidownload", methods=["POST"])

def multi_batch_download():

uName, token = MultiBatchController.ParserTool.parser_name_token_from_request(request)

download_saver = MultiBatchController.MultiBatchTools.saver_copy_and_init(

MultiBatchController.DownloadSaveService, request, basepath)

return MultiBatchController.DownloadTools.download_zip_file(download_saver, uName, token)

2. vue前台

2.1 template

2.2 JS部分

首先需要设置responseType为blob同时还在在headers中指明协议最后在创建blob对象的时候指名类别

3. Axios解码异常/压缩包损坏

我的异常是Mock拦截了blob数据,并强制转码为了str数据所以如果压缩包损坏/数据量不同,需要注意返回的类型是否正确上图注释掉mock模块前,responseType是空,request是MockXMLHttpRequest

相关链接

评论可见,请评论后查看内容,谢谢!!!评论后请刷新页面。