在本地调试时,点击导出提示
has been blocked by CORS policy: No ‘Access-Control-Allow-Origin’ header is present on the requested resource.
原始代码;
public static void exportTemplate(String excelName, Workbook workbook) {
try {
HttpServletResponse response = HttpServletUtil.getResponse();
String fileName = URLEncoder.encode(excelName, "UTF-8");
response.reset();
response.setHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\"");
response.setContentType("application/octet-stream;charset=UTF-8");
ServletOutputStream outputStream = response.getOutputStream();
workbook.write(outputStream);
outputStream.flush();
outputStream.close();
} catch (Exception exception) {
log.error(">>> 导出数据异常:{}", exception);
}
}
解决方案
修改在response.reset(); 后面添加两个行代码,可以解决前端跨域问题。
public static void exportTemplate(String excelName, Workbook workbook) {
try {
HttpServletResponse response = HttpServletUtil.getResponse();
String fileName = URLEncoder.encode(excelName, "UTF-8");
response.reset();
// 解决前端跨域
response.addHeader("Access-Control-Allow-Origin", "*");
//response.addHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE");
response.setHeader("Access-Control-Allow-Headers", "Content-Type");
response.setHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\"");
response.setContentType("application/octet-stream;charset=UTF-8");
ServletOutputStream outputStream = response.getOutputStream();
workbook.write(outputStream);
outputStream.flush();
outputStream.close();
} catch (Exception exception) {
log.error(">>> 导出数据异常:{}", exception);
}
现在又遇到了新的问题,前端下载组件获取流后。无法获取文件名称。
var contentDisposition = res.headers[‘content-disposition’] 获取不到文件信息
在后端添加的
response.setHeader(“Content-Disposition”, “attachment; filename=”" + fileName + “”");
没有添加成功。
前端流下载组件
downloadfile (res) {
this.batchExportLoading = false
var blob = new Blob([res.data], { type: 'application/octet-stream;charset=UTF-8' })
var contentDisposition = res.headers['content-disposition']
var patt = new RegExp('filename=([^;]+\\.[^\\.;]+);*')
var result = patt.exec(contentDisposition)
var filename = result[1]
var downloadElement = document.createElement('a')
var href = window.URL.createObjectURL(blob) // 创建下载的链接
var reg = /^["](.*)["]$/g
downloadElement.style.display = 'none'
downloadElement.href = href
downloadElement.download = decodeURI(filename.replace(reg, '$1')) // 下载后文件名
document.body.appendChild(downloadElement)
downloadElement.click() // 点击下载
document.body.removeChild(downloadElement) // 下载完成移除元素
window.URL.revokeObjectURL(href)
}
debug信息
返回结果打印信息
里面没有 content-disposition 信息。
解决方案:
后端添加 response.setHeader(“Access-Control-Expose-Headers”, “Content-Disposition”);
在使用CORS方式跨域时,浏览器只会返回 默认的头部 Header。
Access-Control-Expose-Headers 响应报头 指示哪些报头可以 公开 为通过列出他们的名字的响应的一部分。
public static void exportTemplate(String excelName, Workbook workbook) {
try {
HttpServletResponse response = HttpServletUtil.getResponse();
String fileName = URLEncoder.encode(excelName, "UTF-8");
response.reset();
// 解决前端跨域
response.addHeader("Access-Control-Allow-Origin", "*");
//response.addHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE");
response.setHeader("Access-Control-Allow-Headers", "Content-Type");
// 需要添加以下配置 否则前获取不到 Content-Disposition
response.setHeader("Access-Control-Expose-Headers", "Content-Disposition");
response.setHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\"");
response.setContentType("application/octet-stream;charset=UTF-8");
ServletOutputStream outputStream = response.getOutputStream();
workbook.write(outputStream);
outputStream.flush();
outputStream.close();
} catch (Exception exception) {
log.error(">>> 导出数据异常:{}", exception);
}
}
返回结果 headers 中存在 content-disposition 值
Access-Control-Allow-Origin 用于设置允许跨域请求源地址 (预检请求和正式请求在跨域时候都会验证)
Access-Control-Allow-Headers 跨域允许携带的特殊头信息字段 (只在预检请求验证)
Access-Control-Allow-Methods 跨域允许的请求方法或者说HTTP动词 (只在预检请求验证)