若依前后端分离框架下载需要授权的url文件,解决跨域问题

一、问题描述:

使用若依前后端分离项目,前台点击下载图片,触发下载事件,而不是直接打开显示图片
若依前后端分离框架下载需要授权的url文件,解决跨域问题_第1张图片

二、解决思路:

前端调用后端自定义下载接口,将需要下载的图片https链接传给后端下载,将二进制(blob)文件流返回给前端,前端用a标签下载

  • 后端需要设置响应头 response.addHeader("Access-Control-Allow-Origin", "*"); 允许跨域
    前端需要设置 responseType: 'blob' 告诉后端前端需要的是blob二进制文件流,否则会导致返回乱码
  • 请求方式一、前端调用request.js方式封装的发送请求方式调用后端自定义下载接口/common/download/url
    或者
    请求方式二、前端发送请求调用后端自定义文件下载接口/common/download/url的代码可以参考:链接指引,下面也有给出

三、前端代码:

①、标签:

   <template slot-scope="scope">
     <el-button
       id="IframeReportImg"
       size="mini"
       type="text"
       icon="el-icon-download"
       @click="handleUpload(scope.row)"
     >下载
     </el-button>
   </template>

②、请求方式一:用request.js封装的请求后端下载接口

//下载图片
export function downloadImgs(params) {
  return request({
    url: '/common/download/url',//后端自定义的下载接口/common/download/url,路径为admin模块的com.ruoyi.web.controller.common;
    responseType: 'blob', //设置后端返回类型为二进制流,不设置会返回乱码
    method: 'get',
    params
  })
}
  handleUpload(row) {
    const url = row.processedImg//图片的https链接
    const imgName = url.substr(url.lastIndexOf('/') + 1)
    downloadImgs({
      url: url
    })
      .then(res => {
        let href = window.URL.createObjectURL(new Blob([res])) // 根据后端返回的url对应的文件流创建URL对象
        const link = document.createElement('a')//创建一个隐藏的a标签
        link.style.display = 'none'
        link.href = href//设置下载的url
        link.download = imgName //设置下载的文件名
        document.body.appendChild(link)
        link.click()
        document.body.removeChild(link)
        window.URL.revokeObjectURL(href) // 释放掉blob对象
      })
  },

③、请求方式二:直接封装请求后端下载接口

handleUpload(row) {
  var url = 'http://后端服务器ip地址:8090/common/download/url?url=' + 图片https链接
   var fileName = url.substr(url.lastIndexOf('/') + 1)
   const xhr = new XMLHttpRequest()
   xhr.open('get', url)
   xhr.responseType = 'blob'//设置后端返回类型为二进制流,不设置会返回乱码
   xhr.setRequestHeader('Authorization', 'Bearer ' + getToken()) // 若依的鉴权token
   xhr.onreadystatechange = function() {
     if (this.readyState === 4 && this.status === 200) {
       const name = fileName || xhr.getResponseHeader('Content-Disposition').split('filename=')[1]
       // 支持IE浏览器
       if (window.navigator && window.navigator.msSaveOrOpenBlob) {
         window.navigator.msSaveOrOpenBlob(this.response, name)
         return
       }
       const href = window.URL.createObjectURL(this.response)
       const link = document.createElement('a')
       link.style.display = 'none'
       link.href = href
       link.setAttribute('download', name)
       document.body.appendChild(link)
       link.click()
       document.body.removeChild(link)
       window.URL.revokeObjectURL(href) // 释放掉blob对象
     }
   }
   xhr.send()
 },

四、后端自定义下载接口/common/download/url代码:

若依前后端分离框架下载需要授权的url文件,解决跨域问题_第2张图片

/**
 * description:根据url下载返回给前端二进制文件流
 *
 * @param request
 * @param response
 * @param url
 */

@GetMapping("/common/download/url")
public void downLoadFromUrl(HttpServletRequest request, HttpServletResponse response, String url) {
    try {
        URL urls = new URL(url);
//            根据url创建URL对象
        BufferedInputStream bis = new BufferedInputStream(urls.openStream());
        byte[] tmp = new byte[1024];
        String name = url.substring(url.lastIndexOf('/') + 1);
        response.reset();
        response.setCharacterEncoding("UTF-8");
        response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
        response.addHeader("Access-Control-Allow-Origin", "*");//后端允许跨域
        response.addHeader("Access-Control-Expose-Headers", "Content-Disposition,download-filename");
//            将文件名转成utf8的字符串形式
        response.addHeader("Content-Disposition", "attachment;filename=" + new String(name.getBytes(), "utf-8"));
//            获取输出流,将文件流返回给前端
        OutputStream out = response.getOutputStream();
        int len = 0;
//            从url指向的链接中读取数据保存到tmp字节数组中,写入到输出流中
        while ((len = bis.read(tmp, 0, 1024)) != -1) {
            out.write(tmp, 0, len);
        }
        bis.close();
        out.close();
    } catch (IOException e) {
        log.error("下载文件失败", e);
    }
}

你可能感兴趣的:(Vue,若依前后端分离,跨域问题,图片下载)