代码如下:
//filePath 是服务器存放文件的路径
File file = new File(filePath + File.separator + fileName);
inputStream = new FileInputStream(file);
outputStream = resp.getOutputStream();
//采用工具类,复制输入流IO对象数据至响应输出流。
//IOUtils.copy(inputStream, outputStream);
int size = 0;
int available = inputStream.available();
byte[] buffer = new byte[1024];
int len = 0;
while ((len = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, len);
size += len;
}
logger.info("源文件大小:{},下载文件大小:{}", available, size);
outputStream.flush();
原文件118332字节
可以看到在输入流写入到输出流之后,其大小还是正常的。 但是下载之后的大小就不正常了,保存出来也不正确且打开异常。变成205KB了。
我查了很多,大部分是说因为写入输出流的时候没有定义长度len,导致每次写入的长度都是定值1024,导致多了一些字符,但明显不不能解决我的问题。最后我把问题想到了框架上,因为这个功能确实是一个很简单的功能,代码看上去也没有错误,不应该。
最终我发现了问题。
public class ResponseWrapper extends HttpServletResponseWrapper {
private ByteArrayOutputStream buffer = null;
private ServletOutputStream out = null;
private PrintWriter writer = null;
public ResponseWrapper(HttpServletResponse resp)
throws IOException {
super(resp);
/**
* 替换默认的输出端,作为response输出数据的存储空间(即真正存储数据的流)
*/
buffer = new ByteArrayOutputStream();
/**
* response输出数据时是调用getOutputStream()和getWriter()方法获取输出流,再将数据输出到输出流对应的输出端的。
* 此处指定getOutputStream()和getWriter()返回的输出流的输出端为buffer,即将数据保存到buffer中。
*/
out = new WapperedOutputStream(buffer);
writer = new PrintWriter(new OutputStreamWriter(buffer, this.getCharacterEncoding()));
}
..........
}
因为重写了HttpServletResponseWrapper ,导致在过滤器里,可以获取倒HttpServletResponse的内容,从而框架获取了输出流进行了处理(框架对出入参的规范化处理或集中加解密等方式)
只需要在过滤器里判断请求的url进行放行,就可以了。
String url = request.getRequestURI();
if (url.contains("download")) {
chain.doFilter(request, response);
return;
}
至此,问腿解决了。真实的巨坑啊。我一直以为是自己写错了,换了N种写法都没有解决,最后突发奇想看看是不是框架对我的数据做了二次加工,结果真的是这个问题。