当前位置:主页 > 网页前端 > JavaScript代码 >

javascript Blob对象实现文件下载

时间:2022-09-11 11:26:31 | 栏目:JavaScript代码 | 点击:

说明

最近遇到一个需求,文件下载,但需要鉴权,这就意味着不能用后台返回下载链接的方式进行下载,因为一旦被别人拿到这条链接,就可以不需要任何权限就直接下载,因此需要换种思路,在一番百度之后,了解到了blob对象,这就是本文要讲的内容

注意:本文仅为记录学习轨迹,如有侵权,联系删除

一、Blob对象

Blob 对象表示一个不可变、原始数据的类文件对象。它的数据可以按文本或二进制的格式进行读取,也可以转换成 ReadableStream 来用于数据操作。

二、前端

blob下载思路:

1) 使用ajax发起请求,指定接收类型为blob(responseType: ‘blob')
2)读取请求返回的头部信息里的content-disposition,返回的文件名就在这里面(或者自定义文件名,可跳过此步骤)
3)使用URL.createObjectURL将请求的blob数据转为可下载的url地址
4)使用a标签下载

代码:

// 下载
export function download(query,newFileName) {
  return request({
    url: '/file/download',
    method: 'get',
    responseType: 'blob',
    params: query
  }).then((res) => {
    /**
     * blob下载思路
     * 1) 使用ajax发起请求,指定接收类型为blob(responseType: 'blob')
     * 2)读取请求返回的头部信息里的content-disposition,返回的文件名就在这里面(或者自定义文件名,可跳过此步骤)
     * 3)使用URL.createObjectURL将请求的blob数据转为可下载的url地址
     * 4)使用a标签下载
     * 
     */
    let blob = res.data
    // 从response的headers中获取filename, 后端response.setHeader("Content-disposition", "attachment; filename=xxxx.docx") 设置的文件名;
    // let patt = new RegExp('filename=([^;]+\\.[^\\.;]+);*')
    // let contentDisposition = decodeURI(res.headers['content-disposition'])
    // let result = patt.exec(contentDisposition)
    // let fileName = result[1]

    //将请求的blob数据转为可下载的url地址
    let url = URL.createObjectURL(blob)
    // 创建一个下载标签<a>
    const aLink = document.createElement('a')
    aLink.href = url
    // 2.直接使用自定义文件名,设置下载文件名称
    aLink.setAttribute('download', newFileName )
    document.body.appendChild(aLink)
    // 模拟点击下载
    aLink.click()
    // 移除改下载标签
    document.body.removeChild(aLink);
  })
}

调用该方法

//下载
    download(row) {
      // filePath:文件路径,例如:e:\upload\
	  // fileName:文件名, 例如:a.xlsx
      let form = {
        filePath: row.filePath,
        fileName: row.fileName,
      };
      //下载,row.fileOriginalName是文件的原始名称,仅仅用于文件下载时起个名字而已
      download(form, row.fileOriginalName);
    }
// 由于本人使用的是阿里的oss服务,所以只需要传个文件路径回去后端,根据文件路径查询oss接口得到返回的文件流即可,例如(BufferedInputStream),在响应头设置好返回的类型即可

三、后端

后端这里用了阿里的oss服务,直接拿到文件流(new BufferedInputStream(ossObject.getObjectContent())),如果是非oss的情况下,只需要读取对应服务器上面的文件(File),转成BufferedInputStream后,直接套用下面的代码即可(即通过response.getOutputStream()设置BufferedOutputStream 就行了)

	// response:响应
	// filePath:文件路径,例如:e:\upload\
	// fileName:文件名, 例如:a.xlsx
   public void download(HttpServletResponse response, String filePath, String fileName) {
        //待下载文件名
        response.reset();
        response.setHeader("Content-Disposition", "attachment;filename=" + fileName);
        response.setContentType("application/octet-stream");
        response.setCharacterEncoding("utf-8");
        // 创建OSSClient实例。
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
        // ossObject包含文件所在的存储空间名称、文件名称、文件元信息以及一个输入流。
        OSSObject ossObject = ossClient.getObject(bucketName, filePath + "/" + fileName);

        BufferedInputStream in = null;
        BufferedOutputStream out = null;

        byte[] buff = new byte[1024];
        int length = 0;
        try {
            in = new BufferedInputStream(ossObject.getObjectContent());
            out = new BufferedOutputStream(response.getOutputStream());
            while ((length = in.read(buff)) != -1){
                out.write(buff,0,length);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if(out != null){
                try {
                    out.flush();
                    out.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(in != null){
                try {
                    in.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
    }

总结

您可能感兴趣的文章:

相关文章