Bootstrap

vue django实现文件下载(跨域问题,前端无法获得filename)

python 代码

      def post(self, request):
        '''下载文件'''
        # 获取请求体中原始的JSON数据
        json_str = request.body
        # 使用json模块将原始的JSON数据转字典
        json_dict = json.loads(json_str)
        masterorder_id = json_dict.get('masterorder_id')
        filepath = json_dict.get('filepath')
        try:
            # obj_master = MasterOrder.objects.get(id=masterorder_id)
            # if eval(obj_master.filepath):
            # for path in eval(obj_master.filepath):
            filename = os.path.basename(filepath)
            file = open(filepath, 'rb')
            response = FileResponse(file)
            response['Content-Type'] = 'application/octet-stream'
            response['Access-Control-Expose-Headers'] = "Content-Disposition, Content-Type"
            response['Content-Disposition'] = 'attachment;filename={}'.format(escape_uri_path(filename))  # 解决中文乱码问题
            return response
        except Exception as e:
            return JsonResponse(
                {'code': 1, 'error': "Failed to submit text, the specific reason:" + str(e)})


async startdownloadFile(info) {
      await axios
        .post(
          this.baseUrl + "/task/orderinfo/",
          {
            //如果没有要传给后台的数据这里可以为空,但最好留着这个花括号,不然后台可能将response当做数据
            masterorder_id: info.master_id,
          },
          {
            responseType: "blob",
          },
          {
            headers: {
              "Content-Type": "application/json;charset=UTF-8",
            },
          }
        )
        .then((response) => {
          //headers请求头的乱码数据转换为中文
          const fileName = decodeURI(
            response.headers['content-disposition'].split(';')[1].split('=')[1]

          );
          //下载文件
          let blob = new Blob([response.data], {
            type: "application/octet-stream",
          });
          let objectUrl = URL.createObjectURL(blob); // 创建URL
          const link = document.createElement("a");
          link.href = objectUrl;
          // link.download = '.xlsx'// 自定义文件名
          //这里是获取后台传过来的文件名
          link.setAttribute("download", fileName);
          link.click(); // 下载文件
          URL.revokeObjectURL(objectUrl); // 释放内存
        })
        .catch((error) => {
          console.log(error);
          alert("下载失败");
        });
    },

有可能会出现跨域问题(拿不到filename)
在这里插入图片描述

有两种解决方案,一种是前端做代理,二种是后端做处理

后端:
产生问题原因
跨域(CORS)请求中,被axios封装好的XMLHttpRequest对象中的方法getResponseHeader()默认只能获取6个基本的字段:Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma。因此,需要获取其他的属性,需要后端在响应的时候去在Access-Control-Expose-Headers中指定content-disposition属性。
所以这是一个后端的锅,是他没有配置,这个问题去找后端,让他在response中配置放行。

response['Access-Control-Expose-Headers'] = "Content-Disposition, Content-Type"

前端

baseUrl: "http://localhost:8080/api"  # 这是前端服务



devServer: {
    proxy: {
      '/api': {
        context: ['/api'],  # 接口的统一前缀
        target: 'http://172.16.10.x:8000'    # 这是请求后端接口
      },
    }
  },
;