vue+django 如何实现压缩包的下载

需求介绍

将django服务器中的压缩包, 从浏览器中下载出来。

难点

压缩包的格式不同于普通文件,需要对请求头做额外设置

代码

django

def download(request):
    logger = logging.getLogger('Django')
    params = json.loads(request.body)
    # 拿到文件在数据库中存储的位置
    media_file = params.get("filePath")
    # 拼接文件路径
    filepath = os.path.join(settings.MEDIA_ROOT, media_file)
    # 拿到文件的名字(该名字包含了文件的格式)
    filename = media_file.split(r'/')[-1]
    file = open(filepath, 'rb')
    response = FileResponse(file)  # 生成文件对象application/msword  application/octet-stream
    response['Content-Type'] = 'application/octet-stream'
    # name.split('.')[0] + '.docx',
    name = filename
    response['Content-Disposition'] = 'attachment;filename ="%s"' % (
        name.encode('utf-8').decode('ISO-8859-1'))
    logger.info("文件下载," + media_file)
    return response

vue

res是上一个请求的返回结果。 这里的responseType只是一个标志位,用于与其他正常的post请求区分。

that.$http({
                    method: "post",
                    url: "/app01/download/",
                    responseType: "blob",
                    params: {
                      filePath: res.filePath,
                    },
                  })
                  .then(
                    (response) => {
                      const filename = res.fileName + ".zip";
                      const blob = new Blob([response], {
                        type: "application/zip",
                      });
                      if (window.navigator.msSaveOrOpenBlob) {
                        navigator.msSaveBlob(blob, filename);
                      } else {
                        var link = document.createElement("a");
                        link.href = window.URL.createObjectURL(blob);
                        link.download = filename;
                        link.click();
                        // 释放内存
                        window.URL.revokeObjectURL(link.href);
                      }
                     
                    },
                    (err) => {
                     
                    }
                  );

压缩包需要额外设置请求头, 否则压缩时会提示文件夹损坏。
之前使用的一直是instance,所以提示文件夹损坏, 新增instance2添加请求头和响应体设置。

import axios from 'axios'
import api from './api'

//创建axios实例对象
let instance = axios.create({
    baseURL: 'http://127.0.0.1:8000', //服务器地址
    timeout: 5000 //默认超时时长
})

let instance2 = axios.create({
    baseURL: 'http://127.0.0.1:8000', //服务器地址
    timeout: 5000, //默认超时时长
    responseType: 'blob',
    headers: { 'Content-Type': 'application/json; application/octet-stream' },

})

//请求拦截器
instance.interceptors.request.use(config => {
    //此处编写请求拦截的代码,一般用于弹出加载窗口
    console.log('正在请求……')
    return config
}, err => {
    console.error('请求失败', err)
})

//响应拦截器
instance.interceptors.response.use(res => {
    //此处对响应数据做处理
    console.log('请求成功!')
    return res //该返回对象会传到请求方法的响应对象中
}, err => {
    // 响应错误处理
    console.log('响应失败!', err)
    // return Promise.reject(err);
})

//封装axios请求方法,参数为配置对象
//option = {method,url,params} method为请求方法,url为请求接口,params为请求参数
async function http(option = {}) {
    let result = null
    if (option.method === 'get' || option.method === 'delete') {
        //处理get、delete请求
        await instance[option.method](
            option.url,
            { params: option.params }
        ).then(res => {
            result = res.data
        }).catch(err => {
            // 这里进行了捕获,方法中不需要再次进行捕获,也捕获不到
            result = err
        })
    } else if (option.method === 'post' || option.method === 'put') {
        //处理post、put请求
        // 如果有参数, 则使用新的instance
        if (option.responseType) {
            await instance2[option.method](
                option.url,
                option.params
            ).then(res => {
                result = res.data
            }).catch(err => {
                result = err
            })
        } else {
            await instance[option.method](
                option.url,
                option.params
            ).then(res => {
                result = res.data
            }).catch(err => {
                result = err
            })
        }
    }

    return result
}

export default http


巨人的肩膀

django部分的代码
django文件夹压缩
压缩包解压时报错文件已损坏
vue部分的代码

你可能感兴趣的:(全栈,#,vue,django,vue.js,python)