Flask下载ZIP或RAR大文件——流式下载

发布时间:2021-12-03 公开文章

背景

Flask在send_from_directory()时遇到Zip文件传输一定大小就重新开始,一开始以为Ngix配置问题,在后来觉得是断点续传的问题,结果瞎搞一通,都没有搞定;最后,采用分段下载搞定。

基础

from flask import Flask, request, Response

app = Flask(__name__)

@app.route('/login', methods=["get", "post"], endpoint='login')
def login():
    if request.method == "POST":
        response = Response()
        name = request.form.get("name")
        pwd = request.form.get("pwd")
        if name and pwd:
            if name == '朱宇' and pwd == '123':
                response.data = '登陆成功'
                # 注意,我这里只是写个例子,不会拿明文的账号密码设置为cookie
                response.set_cookie('name', '朱宇')
                response.set_cookie('pwd', '123')
            else:
                response.data = '用户名或密码错误'
        else:
            response.data = '用户名或密码不能为空'
        return response
    elif request.method == 'GET':
        # 我这里返回字符串表示一个页面,你完全可以写一个html页面,使用render_template这个方法返回
        return 'login.html'

if __name__ == "__main__":
    app.run(debug=True)


先要看懂上面这段代码,精彩的来了。

流式下载

@app.route('/downloadfile/', methods=['GET', 'POST'])
def downloadfile():
    if request.method == 'GET':
        fullfilename = request.args.get('filename')
    # fullfilename = '/root/allfile/123.txt'
        fullfilenamelist = fullfilename.split('/')
        filename = fullfilenamelist[-1]
        filepath = fullfilename.replace('/%s'%filename, '')
        #普通下载
        # response = make_response(send_from_directory(filepath, filename, as_attachment=True))
        # response.headers["Content-Disposition"] = "attachment; filename={}".format(filepath.encode().decode('latin-1'))
        #return send_from_directory(filepath, filename, as_attachment=True)
        #流式读取
        def send_file():
            store_path = fullfilename
            with open(store_path, 'rb') as targetfile:
                while 1:
                    data = targetfile.read(20 * 1024 * 1024)   # 每次读取20M
                    if not data:
                        break
                    yield data

        response = Response(send_file(), content_type='application/octet-stream')
        response.headers["Content-disposition"] = 'attachment; filename=%s' % filename   # 如果不加上这行代码,导致下图的问题
        return response



 

当没有文件名,和文件格式,遇到这种情况,打开F12,查看response.headers 与正常的比较。

 

总结

FLask总会在探索的过程中出现这样或那样的问题,这可能是较Django的缺点吧。