js ajax jquery java文件excel下载处理方式

最近需要在下载的请求头中加入token身份验证,所以传统的form或者url直接下载的方式需要调整成使用ajax,以方便在head中放入token等校验信息,最近研究了两种实现方式,中间踩了很多坑(乱码、FileReader.readAsDataURL: Argument 1 does not implement interface Blob.等问题)

一、使用流的方式+XMLHttpReques方式

后端代码:

HSSFWorkbook wb = ...;//此处省略
response.setContentType("application/vnd.ms-excel");
response.setCharacterEncoding("UTF-8");
response.setHeader("Content-disposition", "attachment;filename=test.xls");
OutputStream outputStream = null;
try {
    outputStream = response.getOutputStream();
    wb.write(outputStream);
} catch (IOException e) {
    e.printStackTrace();
} finally {
    if (outputStream != null) {
        outputStream.flush();
        outputStream.close();
    }
}

前端代码:

function downloada(url,filename) {
    var xhr = new XMLHttpRequest();
    xhr.open('POST', url, true); 
    xhr.setRequestHeader('token', 'xxxxxxx'); //用来做身份校验的字符串
    xhr.responseType = "blob"; // 设置返回类型blob
    // 定义请求完成的处理函数,请求前也可以增加 加载框/禁用下载按钮的相关逻辑
    xhr.onload = function() {
        if (this.status === 200) {
            var blob = this.response;
            var reader = new FileReader();
            reader.readAsDataURL(blob);
            reader.onload = function(e) {
                // 转换完成后创建a标签下载
                var a = document.createElement('a');
                a.download = filename;
                a.href = e.target.result;
                $("body").append(a);
                a.click();
                $(a).remove();
            }
        }
    };
    xhr.send() //发送ajax请求
}

这种方式可以实现,但是尝试把ajax换成jquer的方式会报错:FileReader.readAsDataURL: Argument 1 does not implement interface Blob,使用XMLHttpReques方式正常可用;

二、使用文件Base64字符串+Jquery Ajax方式实现

后端:

HSSFWorkbook wb = ...; //此处省略
File PDFFilePath = new File("test.xls");
FileOutputStream exportXls = new FileOutputStream(PDFFilePath);
wb.write(exportXls);
exportXls.close();
//自定义方法  文件转base64流
String strResult = PDFToBase64(PDFFilePath);
strResult = strResult.replaceAll("\r\n", "");
//... 根据情况是否要删除创建好的无用文件

return Ret.SUCCESS(strResult); //返回给前端json对象(Ret.SUCCESS是自定义方法,为了返回json对象结构)

前端:

<script src="http://cdn.staticfile.org/FileSaver.js/1.3.8/FileSaver.min.js"></script> //引入FileSaver保存js

//工具方法
function b64toFile(b64Data, filename, contentType) {
    let sliceSize = 512;
    let byteCharacters = atob(b64Data);
    let byteArrays = [];
 
    for (let offset = 0; offset < byteCharacters.length; offset += sliceSize) {
        let slice = byteCharacters.slice(offset, offset + sliceSize);
        let byteNumbers = new Array(slice.length);
 
        for (let i = 0; i < slice.length; i++) {
            byteNumbers[i] = slice.charCodeAt(i);
        }
        let byteArray = new Uint8Array(byteNumbers);
        byteArrays.push(byteArray);
    }
 
    let file = new File(byteArrays, filename, {type: contentType});
    return file;
}

//下载时调用的入口方法
function download(){

 $.ajax({
      url: "http://localhost:81/api/code/uncheck/exportAllGroupTest",
      type: "post",
      dataType: "json",
      beforeSend: function(request){
           request.setRequestHeader("Content-Type","application/vnd.ms-excel");
           request.setRequestHeader("token","xxxx");
      },
      success: (res)=>{
         console.log("res:"+res);
         console.log("base64:"+res.data);

      //base64Data 是服务器获取到的数据
        let file = b64toFile(res.data, 'test', 'application/vnd.ms-excel;charset=utf-8');
      //利用FileSaver.js 下载文件为Excel文件
        saveAs(file, "fileName.xls");
    }
  });
}

这种方案的实现原理是,后端把文件转换成了base64字符串,前端通过json拿到文件的字符串后进行逆转换下载;

欢迎关注博主,后续不落下博主的干活文章;

上一篇:js处理异步的几种方式


下一篇:Ajax的基本使用