flask - 上传下载文件


阅读目录

一、上传文件

二、下载文件

引言

本案例前端采用Vue2.0  后端Flask1.0.2,主要实现上传/下载文件功能

1 上传文件

1.1 前端

1.2 后端

2 下载文件

2.1 前端

2.1.1 Blob实现

exportConfig(){
    # 后端接口
    exportConfig(this.ids).then(res => {  # res为make_response()返回结果
        if(res.status === 200){
            const blob = new Blob([res.data],{type:"application/zip"});  #初始化Blob都西昂
            const fileName = 'execute_file.zip';  # 文件名称
            if ('download' in document.createElement('a')) { // 非IE下载
              const elink = document.createElement('a')
              elink.download = fileName
              elink.style.display = 'none'
              elink.href = URL.createObjectURL(blob)
              document.body.appendChild(elink)
              elink.click()
              URL.revokeObjectURL(elink.href) // 释放URL 对象
              document.body.removeChild(elink)
    
            } else { // IE10+下载
              navigator.msSaveBlob(blob, fileName)
            }
            this.$message({
                    message: "导出成功",
                    type: "success"
                });
        }else{
            this.$message.error(res.data.data)
        }
    }) 
}  

2.1.1 原生a标签实现

exportConfig(){
    // 采用a标签的href指定的方式
    const elink = document.createElement('a');
    elink.download = 'execute_file.zip';
    elink.style.display = 'none';
    // elink.target = '_blank';
    elink.href = config.baseUrl +'/接口路径/?ids='+ JSON.stringify(this.ids[0]);
    document.body.appendChild(elink);
    elink.click();
    URL.revokeObjectURL(elink.href); // 释放URL 对象
    document.body.removeChild(elink)
}

2.2 后端

2.2.1 服务 - Services层

def services_export_file():
    """导出文件"""
    obj = ConfigXxx()
    res, err = obj.export()
    if err:
        return response.failed(data=err)
    return res

2.2.2 分模块处理 - Modules层

class ConfigXxx:
    def export(self):
        """导出"""
        p_id = request.values.get('ids')
        if not str(p_id).isdigit():
            return None, f"不支持的导出参数【{p_id}】"
        p_info, err = self.structure_config_data(p_id)
        if err:
            return None, err
        file_handle = File()
        # 生成文件
        dirpath, err = file_handle.generate(p_info)
        if err:
            return None, err
        export_data, err = file_handle.export_zip_file(dirpath)
        if err:
            return None, err
        
        # 移除文件
        file_handle.remove(dirpath)

        # 核心->把生成的数据交给交给make_response处理
        res = make_response(send_file(export_data, attachment_filename='execute_file.zip', as_attachment=True))
        return res, None

2.2.3 文件处理

class File:
    def export_zip_file(self, dirpath):
        """查询导出文件"""
        import os
        import zipfile
        from io import BytesIO
        try:
            memory_file = BytesIO()
            with zipfile.ZipFile(memory_file, "w", zipfile.ZIP_DEFLATED) as zf:
                dirname_list = list()
                for path, dirnames, filenames in os.walk(dirpath):
                    dname = path.split('\\')[-1]
                    if not dirnames:
                        for filename in filenames:
                            zf.write(os.path.join(path, filename), os.path.join(*dirname_list, dname, filename))
                    else:
                        if dirname_list:
                            for filename in filenames:
                                zf.write(os.path.join(path, filename), os.path.join(*dirname_list, dname, filename))
                        else:
                            for filename in filenames:
                                zf.write(os.path.join(path, filename), os.path.join(dname, filename))
                        # 记录目录名称
                        dirname_list.append(dname)
                # zf.setpassword("kk-123456".encode('utf-8'))
            memory_file.seek(0)
            return memory_file, None
        except Exception as e:
            return None, str(e)

2.3 总结

1.前端用Blob实现导出失败,具体原因暂时不详,猜测flask.make_response()生成的文件的流Blob不支持,有知道原因的大神可以回复我一下!
2.原始a标签实现可以对接flask.make_response()下载文件
3.原始a标签实现下载有个隐藏的坑,上述实现方式在后端会有缓存,前端再次访问已经下载过的文件不会触发Services层,目前原因不祥,猜测是flask.make_response()内部注册session,缓存数据了,刨析源码中...

猜你喜欢

转载自www.cnblogs.com/zhangliang91/p/11912991.html