Axios-post请求下载文件

场景背景

1.一般来说,都是使用get请求后台接口,如此后台返回文件流于浏览器,则可直接下载。

2.那么除一般情况,就有特殊情况,比如你的请求接口参数特别长,此时便不可使用get请求,get请求的参数长度是有限的。那么就使用到本文的解决方案。

废话不多说,直接撸代码!!!

一 JAVA后台接口示例

    /**
     * 下载文件
     *
     * @param request  request请求对象
     * @param response response相应对象
     * @param userVO     请求参数-接收前端formData对象
     */
    @RequestMapping("/download")
    @ResponseBody
    public void downloadFile(HttpServletRequest request, HttpServletResponse response, UserVO userVO) throws IOException {
        //得到要下载的文件名
        String fileName = request.getParameter("filename");
        fileName = new String(fileName.getBytes("iso8859-1"), StandardCharsets.UTF_8);
        //上传的文件都是保存在/WEB-INF/upload目录下的子目录当中
        String fileSaveRootPath = request.getServletContext().getRealPath("/WEB-INF/upload");
        //通过文件名找出文件的所在目录
        String path = findFileSavePathByFileName(fileName, fileSaveRootPath);
        //得到要下载的文件
        File file = new File(path + "\\" + fileName);
        //如果文件不存在
        if (!file.exists()) {
            request.setAttribute("message", "您要下载的资源已被删除!!");
            return;
        }
        //处理文件名
        String realName = fileName.substring(fileName.indexOf("_") + 1);
        //设置响应头,控制浏览器下载该文件,此处的文件名要进行编码处理否则前端显示会乱码
        response.setHeader("content-disposition", "attachment;filename=" + URLEncoder.encode(realName, String.valueOf(StandardCharsets.UTF_8)));
        try (//读取要下载的文件,保存到文件输入流
             FileInputStream in = new FileInputStream(path + "\\" + fileName);
             //创建输出流
             OutputStream out = response.getOutputStream()) {

            //创建缓冲区
            byte[] buffer = new byte[1024];
            int len = 0;
            //循环将输入流中的内容读取到缓冲区当中
            while ((len = in.read(buffer)) > 0) {
                //输出缓冲区的内容到浏览器,实现文件下载
                out.write(buffer, 0, len);
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

二 前端代码示例

function exportFn() {
	var userVO = new FormData();
	userVO.append('id', id)
	userVO.append('name', name)

	ax({
		method: 'post',
		url: baseUrl+"/download"),
		data: userVO,
		//重要:相应类型必须为blob
		responseType: 'blob'
	}).then(function (res) {
		var contentDisposition = decodeURI(res.headers["content-disposition"]);
		var fileRegex = /([^(filename=)]+\.xlsx?)$/g;
		var result = contentDisposition.match(fileRegex);
		var fileName = '检查率统计.xlsx';
		if (result.length > 0) {
			fileName = result[0]
		}

		var blob = new Blob([res.data]);
		var url = window.URL.createObjectURL(blob); // 创建 url 并指向 blob
		var a = document.createElement('a');
		a.href = url;
		a.download = fileName;
		a.click();
		window.URL.revokeObjectURL(url); // 释放该 url
		$("input[name=CSRFTid]").hide()
	});
}

 注意事项:

一 后台文件名需要进行编码操作

//设置响应头,控制浏览器下载该文件,此处的文件名要进行编码处理否则前端显示会乱码
response.setHeader("content-disposition", "attachment;filename=" + URLEncoder.encode(realName, String.valueOf(StandardCharsets.UTF_8)));

二 前端文件名称进行解码操作

//从header中获取到包含文件名的信息进行解码操作
var contentDisposition = decodeURI(res.headers["content-disposition"]);

三 前端获取文件名

//从header中取得包含文件名的信息并进行解码
var contentDisposition = decodeURI(res.headers["content-disposition"]);
//匹配文件名的正则
var fileRegex = /([^(filename=)]+\.xlsx?)$/g;
var result = contentDisposition.match(fileRegex);
var fileName = '检查率统计.xlsx';
//取得文件名并赋值
if (result.length > 0) {
	fileName = result[0]
}

后语:

至此,大功告成!!!

你可能感兴趣的:(程序猿之路,技术专栏,下载,文件下载,java,vue.js)