springboot前后端分离项目如何通过前端下载文件资源

前端

前端网络请求使用的axios。

前端需要将axios响应的responseType类型更改为blob,因为responseType默认是json,这会导致返回的文件数据会被json编码导致不可用。

下方的代码总体思想就是将下载的文件数据通过URL.createObjectURL方法创建一个可以通过url访问这个文件数据的对象。使得你可以通过url直接进行下载(如果浏览器支持预览你就会直接进行预览了)。
这会创建一个隐藏的a标签,自触发click后就会自行移除。
至于有没有文件的大小限制就不知道了。
download属性你可能会想了解下。

    // 从接口响应的header获取生成的文件名称(自定义的header)。
    let filename = response.headers['resource-filename']
    // 对文件名进行解码。
    filename = decodeURIComponent(filename);

    // 创建a标签
    const link = document.createElement("a")
    try{
      link.download = filename
      // 2.使用接口返回的数据下载
      link.href = URL.createObjectURL(response.data)
      // 新标签中下载
      link.target = "_blank"
      link.style.display = "none"
      // 将a标签添加到dom中
      document.body.appendChild(link)
      // 下载文件
      link.click()
    }finally {
      link.href && URL.revokeObjectURL(link.href)
      // 从dom中移除a标签
      document.body.removeChild(link)
    }

后端

后端下载你可能需要认识下Content-Disposition,虽然对前后端通过接口进行下载的方式用不到。

切记,setHeader一定要在写入流数据之前就已经设置好,不然底层代码会忽略此次设置。

        // 格式化报告的创建时间
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmm");
        String timeString = dateFormat.format(new Date());

        String filename = URLEncoder.encode("xxx.docx", "UTF-8");

        response.setHeader("Content-Disposition", "attachment;filename=" + filename);

        response.setHeader("resource-filename", filename);

        // 设置响应的参数
        response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);

        // 写入响应流
        ServletOutputStream outputStream = response.getOutputStream();

        // todo 将你要返回的文件流数据写入到outputStream中就行。

关于Spring使用@ResponseBody注解在方法上,但依然想返回流数据,这可以通过org.springframework.http.ResponseEntity实现哦。

从jar文件中读取资源文件。以下三种方法,日后补充。

T.class.getClassLoader().getResource()中进行读取。
this.getClass().getClassLoader().getResource()中进行读取。
org.springframework.core.io.ClassPathResource中进行读取。

参阅

decodeURIComponent
axios req_config

posted @ 2023-03-03 19:10  星小梦  阅读(1570)  评论(0)    收藏  举报