四. 多文件上传及多文件列表展示, 与对象关联的形式
springmvc 也同样支持多文件上传, 需要把 MultipartFile 单对象改成 数组形式 MultipartFile [] 或者是集合形式 List ,习惯用数组形式来接收。
当然,也用两种用法,一个是方法参数,另外一个就是与对象关联, 这里用对象关联的形式进行讲解,顺便把 文件的展示列表也给讲了。
四.一 重新定义 User.java 类的属性
将image 变成 images, 并设置成集合的形式。 imageFile 变成imageFiles, 并且成为数组的形式。
//有多个上传图片的路径的属性 private List<String> images ; //定义属性为imageFiles private MultipartFile [] imageFiles;
老蝴蝶在这儿省略了 setter和getter方法。
四.二 上传文件的 login.jsp 页面
将单文件变成多文件
<body> <h2>两个蝴蝶飞,文件上传使用</h2> <form:form commandName="user" action="login.action" enctype="multipart/form-data" type="post"> <form:label path="name">姓名:</form:label> <form:input path="name"/> <br/><br/> <!-- 可以使用js来动态设置,这里就指定为3个 --> <input type="file" name="imageFiles"> <br/><br/> <input type="file" name="imageFiles"> <br/><br/> <input type="file" name="imageFiles"> <br/><br/> <form:button>提交</form:button> </form:form> </body>
四.三 展示文件的 list.jsp页面
要展示多个, 用c:forEach 标签
不要忘记添加 jstl的core标签
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
页面展示:
<body> 你好,${message}<br/> <c:forEach items="${user.images}" var="imgPath"> <img src="${pageContext.request.contextPath}${imgPath}" width=100 height=100> <br/> </c:forEach> </body>
四.四 后端UserAction 的处理
//转到登录的页面 @RequestMapping(value="toLogin") public String toLogin(Model model){ model.addAttribute("user",new User()); return "user/login"; } //绑定到user对象。 @RequestMapping(value="login") public String login(User user,Model model,HttpServletRequest request){ String message=""; MultipartFile[] files=user.getImageFiles(); if(files!=null&&files.length>0){ List<String> images=new ArrayList<String>(); for(MultipartFile file:files){ //进行单个文件的判断。 if(file!=null&&!file.isEmpty()){ //不为空,即上传了文件 //1. 获取服务器的文件 String path=request.getServletContext().getRealPath("/upload"); //2. 获取上传的文件的名称 String fileName=file.getOriginalFilename(); //3. 实例化构建文件。 File filePath=new File(path,fileName); //4.判断文件,如果父不存在的话,即upload文件夹不存在的话,就创建父级文件夹。 if(!filePath.getParentFile().exists()){ filePath.getParentFile().mkdirs(); } try { file.transferTo(new File(path+File.separator+fileName)); //设置图片的路径。 String imageName="/upload"+"/"+fileName; images.add(imageName); message="文件上传成功"; } catch (IllegalStateException e) { // TODO 自动生成的 catch 块 e.printStackTrace(); message="文件上传失败"; } catch (IOException e) { // TODO 自动生成的 catch 块 e.printStackTrace(); message="文件上传失败"; } } //for 遍历之后,再设置 user.setImages(images); } }else{ message="没有上传文件"; } model.addAttribute("user",user); model.addAttribute("message",message); return "user/list"; }
四.五 springmvc.xml 配置文件,不需要 改变
四.六 运行服务器,进行测试
上传提交:
提交后,展示图片
Tomcat服务器 路径显示:
多文件上传成功。
五. 下载文件
众所皆知, 链接到正确的位置,可以进行下载。 下面,用a 链接看看。
五.一 a 链接显示
将多文件列表那个 list.jsp 的显示图片 <img> ,改成 <a> 链接的话,看看效果怎么样。
<body> 你好,${message}<br/> <ul style="list-style: none;"> <c:forEach items="${user.images}" var="imgPath"> <%-- <img src="${pageContext.request.contextPath}${imgPath}" width=100 height=100> <br/> --%> <li> <a href="${pageContext.request.contextPath}${imgPath}">${imgPath}</a> </li> </c:forEach> </ul> </body>
刷新后展示为:
点击链接,发现会进行查看,并不会下载。
用JS 强行下载呢?
五.二 JS 强制 a链接下载
将上面 的 list.jsp 继续优化,改成,用js事件来进行下载。
<body> 你好,${message}<br/> <ul style="list-style: none;"> <c:forEach items="${user.images}" var="imgPath"> <%-- <img src="${pageContext.request.contextPath}${imgPath}" width=100 height=100> <br/> --%> <li> <a href="javascript:void(0);" onclick="openDownloadDialog('${pageContext.request.contextPath}${imgPath}')">${imgPath}</a> </li> </c:forEach> </ul> <script> function openDownloadDialog(url){ var first = "" , last = "" , name = "" , houZhui = ""; first = url.lastIndexOf("/");//最后一个/的位置 last = url.lastIndexOf(".");//最后一个.的位置 name = url.substr(first+1,last-first-1);//照片名称 houZhui = url.substr(url.lastIndexOf("."));//后缀 var aLink = document.createElement('a');//创建一个虚拟的a标签 aLink.href = url;//这只a标签的url aLink.download = name + houZhui; // 指定保存文件名,可以不要后缀 var event; event = document.createEvent('MouseEvents');//创建一个新的MouseEvent对象 event.initMouseEvent('click', true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null); aLink.dispatchEvent(event); } </script> </body>
刷新页面,当点击链接之后,会弹出下载对话框,可以进行下载。
当这上面,只是js的前端下载, 还需要学习后端的下载。
五.三 服务器后端下载
在UserAction 中添加一个download() 下载的方法,传入的是文件的路径 (也可以传入文件的名称),进行操作
@RequestMapping(value="download") public ResponseEntity<byte[]> download(HttpServletRequest request, @RequestParam(value="filePath") String fileName) throws UnsupportedEncodingException, IOException{ //1 获取项目路径 String contextPath=request.getServletContext().getRealPath("/"); System.out.println("输出name:"+fileName); // 2 拼接下载的文件的路径 File file=new File(contextPath+fileName); System.out.println("输出文件路径:"+file.toString()); //3 将下载的名称,进行格式转换 String downFileName=new String(fileName.getBytes("utf-8"),"ISO-8859-1"); //4 设置浏览器头部信息,可以下载的设置,设置中文编码,避免出现中文不能下载的情况。 HttpHeaders headers=new HttpHeaders(); headers.setContentDispositionFormData("attachment", downFileName); //常见的格式,application/oct_stream headers.setContentType(MediaType.APPLICATION_OCTET_STREAM); return new ResponseEntity<byte[]>(FileUtils.readFileToByteArray(file), headers,HttpStatus.CREATED); }
在前端 重写 list.jsp, a链接的href提交到后端。
<ul style="list-style: none;"> <c:forEach items="${user.images}" var="imgPath"> <li> <a href="download.action?filePath=${imgPath}">${imgPath}</a> </li> </c:forEach> </ul>
重启服务器,进行验证。
谢谢!!!