使用http response编写附件下载功能,当附件是docx时,用office的word打开,会出现文件损坏,是否修复的错误,点击修复又能正常打开。
首先,仔细对比文件发现,下载下来的文件比服务器上的文件多了12个字节,由此可以推断,在IO流写入的时候字节写多了,百度了一番,大部分都说写流的时候控制一下长度。
os.write(buffer, 0, len)的时候要注意不要写os.write(buffer),但是我本身就是按照长度来写的。
最后,尝试设置了一下response contentLength,问题得到解决。
response.setContentLength((int) file.length());
为什么想到了设置contentLength,因为在做feign的时候,做过request的转发,当时设置过contentLength,导致报错,所以这次response的时候尝试了一下,还真行。
File file = new File(toFile);
// 如果文件存在,则进行下载
if (file.exists()) {
// 配置文件下载
// response.setHeader("content-type", "application/octet-stream");
// response.setContentType("application/octet-stream");
// response.setCharacterEncoding("UTF-8");
String mineType = new MimetypesFileTypeMap().getContentType(file.getName());
response.setContentLength((int) file.length());
response.setContentType(mineType);
// 下载文件能正常显示中文
response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(file.getName(), "UTF-8"));
// 实现文件下载
byte[] buffer = new byte[1024];
FileInputStream fis = null;
BufferedInputStream bis = null;
try {
fis = new FileInputStream(file);
bis = new BufferedInputStream(fis);
OutputStream os = response.getOutputStream();
int i = bis.read(buffer);
while (i > 0) {
os.write(buffer, 0, i);
i = bis.read(buffer);
}
message = "解密成功";
sysLog.setMessage(message);
sysLog.setFlag("1");
logService.saveLog(sysLog);
logger.info(sourceFile+"Download successfully!");
return "successfully";
} catch (Exception e) {
e.printStackTrace();
message = "下载失败";
sysLog.setMessage(message);
logger.error(sysLog.getAppCode()+"="+message,e);
logService.saveLog(sysLog);
throw new BaseException(500,message);
} finally {
if (bis != null) {
try {
bis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (fis != null) {
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}