SpringMVC(六)——文件上传和下载
文件上传
1.需要导包
commons-fileupload
commons-io
2.请求方法的参数
MultipartFile类,全称org.springframework.web.multipart.MultipartFile。主要方法有
3.在springmvc-config.xml配置文件上传解析器
<!-- 文件上传解析器 --> <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> <property name="defaultEncoding" value="UTF-8"/> </bean>
还有其他属性可以设置,例如maxUploadSize表示上传文件的最大值等。
4.通过jsp的表单提交请求
(1)method设置为post
(2)enctype设置为multipart/form-data,浏览器会采用二进制流的方式处理表单数据,服务器端会对文件上传的请求进行解析处理。
(3)<input type="file" name="filename" />
测试用的jsp例子
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>文件上传</title> <script> // 判断是否填写上传人并已选择上传文件 function check(){ var name = document.getElementById("name").value; var file = document.getElementById("file").value; if(name==""){ alert("填写上传人"); return false; } if(file.length==0||file==""){ alert("请选择上传文件"); return false; } return true; } </script> </head> <body> <form action="${pageContext.request.contextPath }/testup" method="post" enctype="multipart/form-data" onsubmit="return check()"> 上传人:<input id="name" type="text" name="name" /><br /> 请选择文件:<input id="file" type="file" name="uploadfile" multiple="multiple" /><br /> <input type="submit" value="上传" /> </form> </body> </html>
5.控制器类
@Controller public class FileController { @RequestMapping("/testup") public String testUp(@RequestParam("name")String name,@RequestParam("uploadfile") List<MultipartFile> uploadfile,HttpServletRequest request ) { if(!uploadfile.isEmpty() && uploadfile.size()>0) { for(MultipartFile file:uploadfile) { String originalFilename=file.getOriginalFilename();//获取上传文件的原始名字 String dirPath=request.getServletContext().getRealPath("/upload/");//设置上传文件的保存地址目录 File filePath=new File(dirPath); if(!filePath.exists()) {//如果保存文件的地址不存在,就先创建目录 filePath.mkdirs(); } String newname=name+"_"+UUID.randomUUID()+"_"+originalFilename;//用UUID重新命名,这是通用唯一识别码 System.out.println("name="+name); System.out.println("originalFilename="+originalFilename); System.out.println("dirPath="+dirPath); System.out.println("newname="+newname); try {//使用MultipartFile接口的方法完成文件上传到指定位置 file.transferTo(new File(dirPath + newname)); }catch (Exception e) { e.printStackTrace(); return "error"; } } System.out.println("will return success"); return "success"; }else return "error"; } @RequestMapping("/up") public String upjsp() {//通过MVC_03/up进入初始页面 return "up"; } }
这里的文件上传到workspace\.metadata\.plugins\org.eclipse.wst.server.core\tmp0\wtpwebapps\MVC_03\upload。
文件下载
1.导包
2.客户端页面要有一个超链接
<a href="${pageContext.request.contextPath }/download?filename=1.jpg">文件下载 </a>
需要先存在1.jpg这个文件,复制粘贴也好,文件上传进去的也好。
3.控制器类写一个方法下载文件(下面代码会有中文乱码问题)
@RequestMapping("/download") public ResponseEntity<byte[]> testDown(HttpServletRequest request,String filename) throws Exception{ String path=request.getServletContext().getRealPath("/upload/");//指定要下载的文件所在的路径 File file=new File(path+File.separator+filename);//创建该文件对象 HttpHeaders headers=new HttpHeaders();//设置响应头 headers.setContentDispositionFormData("attachment", filename);//通知浏览器以下载的方式打开文件 headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);return new ResponseEntity<byte[]>(FileUtils.readFileToByteArray(file),headers,HttpStatus.OK); }
指定要下载名为filename的文件,HttpStatus.OK(200)表示协议状态,服务器已经成功处理请求。不能用Byte[],亦不解。
4.解决中文乱码问题
(1)在前端页面对编码统一,中文转UTF-8
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@page import="java.net.URLEncoder"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>下载页面</title> </head> <body> <a href="${pageContext.request.contextPath }/download?filename=<%=URLEncoder.encode("壁纸.jpg", "UTF-8")%>"> 中文名称文件下载 </a> </body> </html>
第3行的URLEncoder是Servlet API提供的类。
第13行的encode(String s,String enc)方法是将前者的中文名转化为后者UTF-8编码。这里是先提供了一个壁纸.jpg的文件。
(2)后台控制器再把UTF-8转中文
//UTF-8转中文,写死的模板方法 public String getFilename(HttpServletRequest request, String filename) throws Exception { // IE不同版本User-Agent中出现的关键词 String[] IEBrowserKeyWords = { "MSIE", "Trident", "Edge" }; // 获取请求头代理信息 String userAgent = request.getHeader("User-Agent"); for (String keyWord : IEBrowserKeyWords) { if (userAgent.contains(keyWord)) { //IE内核浏览器,统一为UTF-8编码显示 return URLEncoder.encode(filename, "UTF-8"); } } //火狐等其它浏览器统一为ISO-8859-1编码显示 return new String(filename.getBytes("UTF-8"), "ISO-8859-1"); } @RequestMapping("/download") public ResponseEntity<byte[]> testDown(HttpServletRequest request, String filename) throws Exception { String path = request.getServletContext().getRealPath("/upload/");// 指定要下载的文件所在的路径 File file = new File(path + File.separator + filename);// 创建该文件对象 filename=this.getFilename(request, filename); HttpHeaders headers = new HttpHeaders();// 设置响应头 headers.setContentDispositionFormData("attachment", filename);// 通知浏览器以下载的方式打开文件 headers.setContentType(MediaType.APPLICATION_OCTET_STREAM); return new ResponseEntity<byte[]>(FileUtils.readFileToByteArray(file), headers, HttpStatus.OK); }