项目中经常遇到文件上传下载的功能,springMVC里也提供了文件上传下载的相关功能,下面直接上代码,使用springmvc的ResponseEntity实现日志文件下载。
下载的流程:
1.获取文件源(我这里是String类型的文本日志)
2.将源文件转化为对应的输入流
3.将输入流读取到缓冲区
4.设置浏览器请求头信息,请求状态
5.把流以ResponseEntity的形式返回给客户端
6.记得关闭流。
然后客户端就收到流信息就会按照文件下载的方式开了(由于http的头信息被设置了content-dispostion,所以浏览器收到服务端返回的流会以文件保存的方式打开)。
@RequestMapping(value="/downloadLog")
public ResponseEntity<byte[]> downloadLog(String id,HttpServletRequest request) throws Exception{
String envName=envService.findEnvironmentById(id).getEnvironmentName()+"log.txt";
InputStream input=new ByteArrayInputStream(this.getLog(id).getBytes());
byte[] buff=new byte[input.available()]; // 获取文件大小
input.read(buff) ;
HttpHeaders headers=new HttpHeaders();
headers.add("Content-Disposition", "attachment;filename="+URLEncoder.encode(envName, "UTF-8"));
HttpStatus status=HttpStatus.OK;
ResponseEntity<byte[]> entity=new ResponseEntity<byte[]>(buff,headers,status);
input.close();
return entity;
}
写完后,测了测,发现在google浏览器能上能正常下载且文件名不会乱码,而在火狐浏览器上会乱码,而文件名是用URLEncoder.encode()方法统一编码的,所以问题肯定是火狐浏览器本身兼容的问题。于是查资料,问题出在其他浏览都是统一的unicode编码,而火狐是iso-8859-1编码,所以解决方法是:判断浏览器的种类,如果是火狐,重新编码,修改后的代码如下:
@RequestMapping(value="/downloadLog")
public ResponseEntity<byte[]> downloadLog(String id,HttpServletRequest request) throws Exception{
String envName=envService.findEnvironmentById(id).getEnvironmentName()+"log.txt";
InputStream input=new ByteArrayInputStream(this.getLog(id).getBytes());
byte[] buff=new byte[input.available()]; // input.available()获取文件大小,并实例化相应大小的字节数组
input.read(buff) ;//从输入流中读取全部字节并存储到 buff中。
HttpHeaders headers=new HttpHeaders();
if(getBrowser(request).equals("FF")){//如果是火狐,解决火狐中文名乱码问题
envName = new String(envName.getBytes("UTF-8"),"iso-8859-1");
headers.add("Content-Disposition", "attachment;filename="
+ envName);
}else{
headers.add("Content-Disposition", "attachment;filename="
+URLEncoder.encode(envName, "UTF-8"));
}
HttpStatus status=HttpStatus.OK;
ResponseEntity<byte[]> entity=new ResponseEntity<byte[]>(buff,headers,status);
input.close();
return entity;
}
// 判断浏览器种类的方法
private String getBrowser(HttpServletRequest request) {
String UserAgent = request.getHeader("USER-AGENT").toLowerCase();
if (UserAgent != null) {
if (UserAgent.indexOf("msie") >= 0)
return "IE";
if (UserAgent.indexOf("firefox") >= 0)
return "FF";
if (UserAgent.indexOf("safari") >= 0)
return "SF";
}
return null;
}
注:判断l浏览器种类写的不全,可以自行添加更多种类的浏览器。
值得注意的是:ajax请求无法响应下载功能因为response原因,一般请求浏览器是会处理服务器输出的response,例如生成png、文件下载等,然而ajax请求只是个“字符型”的请求,即请求的内容是以文本类型存放的。文件的下载是以二进制形式进行的,虽然可以读取到返回的response,但只是读取而已,是无法执行的,说白点就是js无法调用到浏览器的下载处理机制和程序。
因此可以通过标签链接的方法直接请求下载地址,或者在js方法里使用window.location.href等等类似的方法进行下载。
最后看一下效果:
The End~