上篇文章写到了文件上传,这次就谈谈文件下载:
其实文件上传下载无非就是通过io流与http协议request和response来传输文件
而文件下载就是将文件io放到response的body(也就是http响应体)中从而返回给客户端,要注意的是需要对响应头进行设置:
httpheader的Content-disposition :
MIME(Multipurpose Internet Mail Extensions)多用途互联网邮件扩展类型。是设定某种扩展名的文件用一种应用程序来打开的方式类型
是 MIME 协议的扩展,MIME 协议指示 MIME 用户代理如何显示附加的文件。当浏览器接收到头时,它会激活文件下载对话框;
注意:必须添加一个attachment(附件)字符串参数,可以询问是否下载文件;
而且可以传一个文件名过去,它的文件名框自动填充了头中指定的文件名。
httpheader的Content-Type:
Content-Type 用于指示资源的MIME类型
- 在响应头中,告诉客户端实际返回内容的类型
- 在请求头中,告诉服务器实际发送的数据类型
servlet下载的方法:
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//通过路径得到一个输入流String path = this.getServletContext().getRealPath("/WEB-INF/classes/111.jpg");FileInputStream fis = new FileInputStream(path);//创建字节输出流ServletOutputStream sos = response.getOutputStream();//得到要下载的文件名String fileName = path.substring(path.lastIndexOf("\\")+1);//设置文件名的编码,将不安全的文件名改为UTF-8fileName = URLEncoder.encode(fileName,"UTF-8");//告知客户端要下载文件response.setHeader("content-disposition","attachment;filename="+fileName);response.setHeader("content-type","image/jpeg");//执行输出操作int len = 1;byte[] buff = new byte[1024];while((len=fis.read(buff))!=-1){sos.write(buff,0,len);}//关闭资源sos.close();fis.close();}
在SpringMVC和SpringBoot中:
由于用到了框架,所以可以不要去直接操作response,而是通过返回一个ResponseEntity<byte[]>(也就是相应实体),通过设置实体的相应头和响应体来实现下载:
在把文件转化成字节数组的时候有两种方法,一种是原生的:
注:
【
inputStream的available是用来获取io的字节数的,一般从本地读取时可以用,如果是从网络传输的io流则不太准确,因为网络传输是分段传的。具体可网上查找。
org.springframework.http.MediaType:声明了content-type的各种类型。
org.springframework.http.HttpStatus:提供了一些状态码,不一定非要写CREATED(201),只是标识一下请求成功时的状态码而已,可以自行选择。
】
@GetMappingpublic ResponseEntity<byte[]> download() throws IOException {byte[] body=null;
String path="F:/photo/avatar.png";File file=new File(path);
HttpHeaders headers=new HttpHeaders();// 通知浏览器以下载文件方式打开headers.setContentDispositionFormData("attachment","FILENAME.jpg");headers.setContentType(MediaType.IMAGE_JPEG);
FileInputStream fis=new FileInputStream(file);body=new byte[fis.available()];fis.read(body);
return new ResponseEntity<byte[]>(body,headers, HttpStatus.CREATED);}
还有一种是利用commons-io工具包来从输入流中来读取出文件的字节数组:
使用前需导包:
<dependency><groupId>commons-io</groupId><artifactId>commons-io</artifactId><version>2.6</version></dependency>
使用代码:
@GetMappingpublic ResponseEntity<byte[]> download() throws IOException {String path="F:/photo/avatar.png";File file=new File(path);
HttpHeaders headers=new HttpHeaders();headers.setContentDispositionFormData("attachment","FILENAME.jpg");headers.setContentType(MediaType.IMAGE_JPEG);
return new ResponseEntity<byte[]>(FileUtils.readFileToByteArray(file),headers, HttpStatus.CREATED);}
参考:
https://blog.csdn.net/yalishadaa/article/details/71374937(不使用commons.io)