springMVC实现文件下载功能(解决火狐浏览器文件名乱码问题)

项目中经常遇到文件上传下载的功能,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~

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章