美文网首页
Axios post 文件下载

Axios post 文件下载

作者: 赛亚人之神 | 来源:发表于2018-11-30 10:15 被阅读144次

    javascript 代码如下

     /* 下载方法 */
    downFile(blob, fileName) {
     // 非IE下载
     if ('download' in document.createElement('a')) {
       let link = document.createElement('a');
       link.href = window.URL.createObjectURL(blob); // 创建下载的链接
       link.download = fileName; // 下载后文件名
       link.style.display = 'none';
       document.body.appendChild(link);
       link.click(); // 点击下载
       window.URL.revokeObjectURL(link.href); // 释放掉blob对象
       document.body.removeChild(link); // 下载完成移除元素
     } else {
       // IE10+下载
       window.navigator.msSaveBlob(blob, fileName);
     }
    },
    downloadFile(url, data) {
        let requestData = Object.assign({}, data, {
          accessToken: sessionStorage.getItem('accessToken')
        });
    
        // 响应类型:arraybuffer, blob
        axios.post(url, requestData, {responseType: 'blob'}).then(resp => {
          let headers = resp.headers;
          let contentType = headers['content-type'];
    
          console.log('响应头信息', headers);
          if (!resp.data) {
            console.error('响应异常:', resp);
            return false;
          } else {
            console.error('下载文件:', resp);
            const blob = new Blob([resp.data], {type: contentType});
    
            const contentDisposition = resp.headers['content-disposition'];
            let fileName = 'unknown';
            if (contentDisposition) {
              fileName = window.decodeURI(resp.headers['content-disposition'].split('=')[1]);
            }
            console.log('文件名称:', fileName);
            this.downFile(blob, fileName);
          }
        }).catch(function (error) {
            console.log(error);
        });
    }
    

    注意: 两种responseType的区别

    1. arrarybuffer: 响应的 data 如下图

      image.png
    2. blob:响应的 data 如下图

      image.png

    遇到的坑:

    1. 无法获取响应头(即无法获取文件名): content-disposition

    In case of CORS requests, browsers can only access the following response headers by default:

    • Cache-Control
    • Content-Language
    • Content-Type
    • Expires
    • Last-Modified
    • Pragma
      If you would like your client app to be able to access other headers, you need to set the Access-Control-Expose-Headers header on the server: Access-Control-Expose-Headers: Access-Token, Uid

    解决方法1:

    response.setHeader("Access-Control-Expose-Headers", "Content-Disposition");
    

    解决方法2:在跨域中设置 exposeHeaders

    @Bean
    CorsConfigurationSource corsConfigurationSource() {
    
        CorsConfiguration configuration = new CorsConfiguration();
        configuration.setAllowCredentials(true);
        configuration.setAllowedOrigins(Arrays.asList(FRONT_END_SERVER));
        configuration.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "DELETE"));
        configuration.setAllowedHeaders(Arrays.asList("X-Requested-With","Origin","Content-Type","Accept","Authorization"));
    
        // This allow us to expose the headers
        configuration.setExposedHeaders(Arrays.asList("Access-Control-Allow-Headers", "Authorization, x-xsrf-token, Access-Control-Allow-Headers, Origin, Accept, X-Requested-With, " +
                "Content-Type, Access-Control-Request-Method, Access-Control-Request-Headers"));
    
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", configuration);
        return source;
    }
    
    1. 下载的文件名乱码
      将文件名进行 utf-8 编码
    String fileName = URLEncoder.encode("导入成交比模板.xls", "UTF-8");
    response.setHeader("Content-Disposition", "attachment;filename="+fileName);
    

    后端主要 java 代码如下:

    // 题头
    List<String[]> headNameList = statisticsService.getExcelHeader("downLoad");
    // 生成导入模板
    HSSFWorkbook wb = ExcelUtil.exportTemplate("导入成交比模板", null, headNameList);
    // 设置导出格式为Excel
    response.setContentType("application/vnd.ms-excel");
    // 设置文件名并解决中文乱码
    
    String fileName = URLEncoder.encode("导入成交比模板.xls", "UTF-8");
    response.setHeader("Content-Disposition", "attachment;filename="+fileName);
    response.setHeader("Access-Control-Expose-Headers", "Content-Disposition");
    
    response.setHeader("Pragma", "No-cache");
    response.setHeader("Cache-Control", "No-cache");
    response.setDateHeader("Expires", 0);
    
    // 声明输出流
    OutputStream ouputStream = response.getOutputStream();
    // 输出文件
    wb.write(ouputStream);
    ouputStream.flush();
    ouputStream.close();
    

    参考连接:

    1. https://stackoverflow.com/questions/37897523/axios-get-access-to-response-header-fields
    2. Access-Control-Expose-Headers
    3. https://www.kancloud.cn/yunye/axios/234845

    相关文章

      网友评论

          本文标题:Axios post 文件下载

          本文链接:https://www.haomeiwen.com/subject/rvyccqtx.html