spingboot项目之文件下载接口跨域问题
现状
- springboot 2.6.2工程配置了全局跨域
@Configuration
public class SimpleCORSFilter {
@Bean
public CorsFilter corsFilter() {
final UrlBasedCorsConfigurationSource urlBasedCorsConfigurationSource = new UrlBasedCorsConfigurationSource();
final CorsConfiguration corsConfiguration = new CorsConfiguration();
/*是否允许请求带有验证信息*/
corsConfiguration.setAllowCredentials(true);
/*允许访问的客户端域名*/
corsConfiguration.addAllowedOrigin("*");
/*允许服务端访问的客户端请求头*/
corsConfiguration.addAllowedHeader("*");
/*允许访问的方法名,GET POST等*/
corsConfiguration.addAllowedMethod("*");
urlBasedCorsConfigurationSource.registerCorsConfiguration("/**", corsConfiguration);
return new CorsFilter(urlBasedCorsConfigurationSource);
}
}
- 有普通http接口,用json交互,有文件上传下载接口
- 前端vue项目,版本2.6
问题
- 所有接口在前端dev环境下调试通过,dev环境设置了本地代理
-
前端页面打包后,访问其他接口都正常,唯独有几个文件下载接口控制台提示跨域错误
cors error
尝试
-
在下载的接口所在的class上加上
@CrosOrigin
注解,未果。 -
在下载接口的方法上加
@CrosOrigin(origins= "http://127.0.0.1:8020")
,未果 -
参考SpringBoot 中实现跨域的5种方式的几张方式都尝试了,未果。
-
搜索引擎搜索"springboot 文件下载跨域", 搜到类似如下代码:
public static void downloadFile(HttpServletResponse resp, String name, String downloadPath) throws IOException {
String filePath = null;
try {
filePath= URLDecoder.decode(downloadPath,"UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
//String realPath = "D:" + File.separator + "apache-tomcat-8.5.15" + File.separator + "files";
String realPath=filePath;//项目路径下你存放文件的地方
String path = realPath + File.separator + name;//加上文件名称
File file = new File(path);
if(!file.exists()){
throw new IOException("文件不存在");
}
name = new String(name.getBytes("GBK"), "ISO-8859-1");
resp.reset();
/*
* 跨域配置
* */
resp.addHeader("Access-Control-Allow-Origin", "*");
resp.addHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE");
resp.addHeader("Access-Control-Allow-Headers", "Content-Type");
resp.setContentType("application/octet-stream");
resp.setCharacterEncoding("utf-8");
resp.setContentLength((int) file.length());
resp.setHeader("Content-Disposition", "attachment;filename=" + name);
byte[] buff = new byte[1024];
BufferedInputStream bis = null;
OutputStream os = null;
try {
os = resp.getOutputStream();
bis = new BufferedInputStream(new FileInputStream(file));
int i = 0;
while ((i = bis.read(buff)) != -1) {
os.write(buff, 0, i);
os.flush();
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
bis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
- 重点:
resp.reset();
/*
* 跨域配置
* */
resp.addHeader("Access-Control-Allow-Origin", "*");
resp.addHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE");
resp.addHeader("Access-Control-Allow-Headers", "Content-Type");
- 启发
response.reset()调用以后,全局设置的跨域header就丢了,因此重新设置的。
解决
在代码里搜索response.reset()
,果然搜到了好几处,把下载里的这个句删除以后测试,通过。
分析
reset()方法:Clears any data that exists in the buffer as well as the status code and headers. If the response has been committed, this method throws an IllegalStateException.
————————————————
使用场景是这样的:一般用于下载文件excel操作时,空白行的出现原因,jsp代码编译后产生。就是有jsp生成html文件的时候,html文件内部会出现很多空白行。下载后的文件内的空白行也是这样产生的。
因此,需要 response.reset() 来清除首部的空白行。
这个场景如果要用的话,应该用resetBuffer()
,
resetBuffer():
Clears the content of the underlying buffer in the response without clearing headers or status code. If the response has been committed, this method throws an
IllegalStateException.
可以看到resetBuffer方法与reset方法的区别是,头和状态码没有清除。
————————————————
参考
springBoot文件下载跨域问题
response.reset() 与response.resetbuffer使用场景`