SpringMVC文件上传中要解决的问题大汇总
作者:Lansonli
这篇文章主要介绍了SpringMVC文件上传中要解决的问题,主要有中文文件名编码问题,文件位置存储问题以及文件名冲突问题等等,本文结合实例代码给大家介绍的非常详细,需要的朋友可以参考下
SpringMVC文件上传中要解决的问题
一、中文文件名编码问题
通过过滤器解决
二、文件位置存储问题
放在当前项目下,作为静态资源,这样可以通过URL访问。
package com.lanson.controller; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.multipart.MultipartFile; import javax.servlet.http.HttpServletRequest; import java.io.File; import java.io.IOException; /** * @Author: Lansonli * @Description: MircoMessage:Mark_7001 */ @Controller public class FileUploadController { @ResponseBody @RequestMapping("fileUpload.do") public String fileUpload(MultipartFile headPhoto, HttpServletRequest req) throws IOException { // 指定文件存储目录为我们项目部署环境下的upload目录 String realPath = req.getServletContext().getRealPath("/upload"); File dir = new File(realPath); // 如果不存在则创建目录 if(!dir.exists()){ dir.mkdirs(); } // 获取文件名 String originalFilename = headPhoto.getOriginalFilename(); // 文件存储位置 File file =new File(dir,originalFilename); // 文件保存 headPhoto.transferTo(file); return "OK"; } }
在SpringMVC中配置静态资源放行
<mvc:resources mapping="/upload/**" location="/upload/"></mvc:resources>
三、文件名冲突问题
使用UUID对文件名进行重命名。
package com.lanson.controller; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.multipart.MultipartFile; import javax.servlet.http.HttpServletRequest; import java.io.File; import java.io.IOException; import java.util.UUID; /** * @Author: Lansonli * @Description: MircoMessage:Mark_7001 */ @Controller public class FileUploadController { @ResponseBody @RequestMapping("fileUpload.do") public String fileUpload(MultipartFile headPhoto, HttpServletRequest req) throws IOException { // 指定文件存储目录为我们项目部署环境下的upload目录 String realPath = req.getServletContext().getRealPath("/upload"); File dir = new File(realPath); // 如果不存在则创建目录 if(!dir.exists()){ dir.mkdirs(); } // 获取文件名 String originalFilename = headPhoto.getOriginalFilename(); // 避免文件名冲突,使用UUID替换文件名 String uuid = UUID.randomUUID().toString(); // 获取拓展名 String extendsName = originalFilename.substring(originalFilename.lastIndexOf(".")); // 新的文件名 String newFileName=uuid.concat(extendsName); // 文件存储位置 File file =new File(dir,newFileName); // 文件保存 headPhoto.transferTo(file); return "OK"; } }
四、控制文件类型和大小
package com.lanson.controller; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.multipart.MultipartFile; import javax.servlet.http.HttpServletRequest; import java.io.File; import java.io.IOException; import java.util.HashMap; import java.util.Map; import java.util.UUID; /** * @Author: Lansonli * @Description: MircoMessage:Mark_7001 */ @Controller public class FileUploadController { @ResponseBody @RequestMapping("fileUpload.do") public Map<String,String> fileUpload(MultipartFile headPhoto, HttpServletRequest req) throws IOException { Map<String,String> map=new HashMap<>(); // 控制文件大小 if(headPhoto.getSize()>1024*1024*5){ map.put("message", "文件大小不能超过5M"); return map; } // 指定文件存储目录为我们项目部署环境下的upload目录 String realPath = req.getServletContext().getRealPath("/upload"); File dir = new File(realPath); // 如果不存在则创建目录 if(!dir.exists()){ dir.mkdirs(); } // 获取文件名 String originalFilename = headPhoto.getOriginalFilename(); // 避免文件名冲突,使用UUID替换文件名 String uuid = UUID.randomUUID().toString(); // 获取拓展名 String extendsName = originalFilename.substring(originalFilename.lastIndexOf(".")); // 控制文件类型 if(!extendsName.equals(".jpg")){ map.put("message", "文件类型必须是.jpg"); return map; } // 新的文件名 String newFileName=uuid.concat(extendsName); // 文件存储位置 File file =new File(dir,newFileName); // 文件保存 headPhoto.transferTo(file); // 上传成功之后,把文件的名字和文件的类型返回给浏览器 map.put("message", "上传成功"); map.put("newFileName", newFileName); map.put("filetype", headPhoto.getContentType()); return map; } }
通过文件上传解析组件控制。
但是会出现异常,后期可以可以配置一个异常解析器解决。
<!--文件上传解析组件 id必须为multipartResolver springmvc默认使用该id找该组件 --> <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> <!--设置文件大小--> <property name="maxUploadSizePerFile" value="10"></property> </bean>
五、上传图片回显问题
后天已经将图片的文件名响应给浏览器。
前端代码
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>Title</title> <script type="text/javascript" src="js/jquery.min.js"></script> <script type="text/javascript"> $(function(){ $("#uploadFile").click(function(){ // 获取要上传的文件 var photoFile =$("#photo")[0].files[0] if(photoFile==undefined){ alert("您还未选中文件") return; } // 将文件装入FormData对象 var formData =new FormData(); formData.append("headPhoto",photoFile) // ajax向后台发送文件 $.ajax({ type:"post", data:formData, url:"fileUpload.do", processData:false, contentType:false, success:function(result){ // 接收后台响应的信息 alert(result.message) // 图片回显 $("#headImg").attr("src","upload/"+result.newFileName); } }) }) }) </script> </head> <body> <form action="addPlayer" method="get"> <p>账号<input type="text" name="name"></p> <p>密码<input type="text" name="password"></p> <p>昵称<input type="text" name="nickname"></p> <p>头像: <br/> <input id="photo" type="file"> <br/> <img id="headImg" style="width: 200px;height: 200px" alt="你还未上传图片"> <br/> <a id="uploadFile" href="javascript:void(0)" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" >立即上传</a> </p> <p><input type="submit" value="注册"></p> </form> </body> </html>
六、进度条问题
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>Title</title> <style> .progress { width: 200px; height: 10px; border: 1px solid #ccc; border-radius: 10px; margin: 10px 0px; overflow: hidden; } /* 初始状态设置进度条宽度为0px */ .progress > div { width: 0px; height: 100%; background-color: yellowgreen; transition: all .3s ease; } </style> <script type="text/javascript" src="js/jquery.min.js"></script> <script type="text/javascript"> $(function(){ $("#uploadFile").click(function(){ // 获取要上传的文件 var photoFile =$("#photo")[0].files[0] if(photoFile==undefined){ alert("您还未选中文件") return; } // 将文件装入FormData对象 var formData =new FormData(); formData.append("headPhoto",photoFile) // ajax向后台发送文件 $.ajax({ type:"post", data:formData, url:"fileUpload.do", processData:false, contentType:false, success:function(result){ // 接收后台响应的信息 alert(result.message) // 图片回显 $("#headImg").attr("src","upload/"+result.newFileName); }, xhr: function() { var xhr = new XMLHttpRequest(); //使用XMLHttpRequest.upload监听上传过程,注册progress事件,打印回调函数中的event事件 xhr.upload.addEventListener('progress', function (e) { //loaded代表上传了多少 //total代表总数为多少 var progressRate = (e.loaded / e.total) * 100 + '%'; //通过设置进度条的宽度达到效果 $('.progress > div').css('width', progressRate); }) return xhr; } }) }) }) </script> </head> <body> <form action="addPlayer" method="get"> <p>账号<input type="text" name="name"></p> <p>密码<input type="text" name="password"></p> <p>昵称<input type="text" name="nickname"></p> <p>头像: <br/> <input id="photo" type="file"> <%--图片回显--%> <br/> <img id="headImg" style="width: 200px;height: 200px" alt="你还未上传图片"> <br/> <%--进度条--%> <div class="progress"> <div></div> </div> <a id="uploadFile" href="javascript:void(0)" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" >立即上传</a> </p> <p><input type="submit" value="注册"></p> </form> </body> </html>
七、单独准备文件存储服务器
分服务器上传作用
- 数据库服务器:运行我们的数据库
- 缓存和消息服务器:负责处理大并发访问的缓存和消息
- 文件服务器:负责存储用户上传文件的服务器。
- 应用服务器:负责部署我们的应用
在实际开发中,我们会有很多处理不同功能的服务器。(注意:此处说的不是服务器集群)
总结:分服务器处理的目的是让服务器各司其职,从而提高我们项目的运行效率。
分服务器工作示意图
单独解压一个Tomcat作为文件服务器
设置远程服务器端口号
远程服务器中设置非只读
webapps下创建一个upload目录
启动测试
项目中导入依赖
<dependency> <groupId>com.sun.jersey</groupId> <artifactId>jersey-client</artifactId> <version>1.19</version> </dependency>
controller代码
package com.lanson.controller; import com.sun.jersey.api.client.Client; import com.sun.jersey.api.client.WebResource; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.multipart.MultipartFile; import javax.servlet.http.HttpServletRequest; import java.io.File; import java.io.IOException; import java.util.HashMap; import java.util.Map; import java.util.UUID; /** * @Author: Lansonli * @Description: MircoMessage:Mark_7001 */ @Controller public class FileUploadController { // 文件存储位置 private final static String FILESERVER="http://192.168.8.109:8090/upload/"; @ResponseBody @RequestMapping("fileUpload.do") public Map<String,String> fileUpload(MultipartFile headPhoto, HttpServletRequest req) throws IOException { Map<String,String> map=new HashMap<>(); // 获取文件名 String originalFilename = headPhoto.getOriginalFilename(); // 避免文件名冲突,使用UUID替换文件名 String uuid = UUID.randomUUID().toString(); // 获取拓展名 String extendsName = originalFilename.substring(originalFilename.lastIndexOf(".")); // 新的文件名 String newFileName=uuid.concat(extendsName); // 创建 sun公司提供的jersey包中的client对象 Client client=Client.create(); WebResource resource = client.resource(FILESERVER + newFileName); // 文件保存到另一个服务器上去了 resource.put(String.class, headPhoto.getBytes()); // 上传成功之后,把文件的名字和文件的类型返回给浏览器 map.put("message", "上传成功"); map.put("newFileName",newFileName); map.put("filetype", headPhoto.getContentType()); return map; } }
页面代码
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>Title</title> <style> .progress { width: 200px; height: 10px; border: 1px solid #ccc; border-radius: 10px; margin: 10px 0px; overflow: hidden; } /* 初始状态设置进度条宽度为0px */ .progress > div { width: 0px; height: 100%; background-color: yellowgreen; transition: all .3s ease; } </style> <script type="text/javascript" src="js/jquery.min.js"></script> <script type="text/javascript"> $(function(){ $("#uploadFile").click(function(){ // 获取要上传的文件 var photoFile =$("#photo")[0].files[0] if(photoFile==undefined){ alert("您还未选中文件") return; } // 将文件装入FormData对象 var formData =new FormData(); formData.append("headPhoto",photoFile) // ajax向后台发送文件 $.ajax({ type:"post", data:formData, url:"fileUpload.do", processData:false, contentType:false, success:function(result){ // 接收后台响应的信息 alert(result.message) // 图片回显 $("#headImg").attr("src","http://192.168.8.109:8090/upload/"+result.newFileName); }, xhr: function() { var xhr = new XMLHttpRequest(); //使用XMLHttpRequest.upload监听上传过程,注册progress事件,打印回调函数中的event事件 xhr.upload.addEventListener('progress', function (e) { //loaded代表上传了多少 //total代表总数为多少 var progressRate = (e.loaded / e.total) * 100 + '%'; //通过设置进度条的宽度达到效果 $('.progress > div').css('width', progressRate); }) return xhr; } }) }) }) </script> </head> <body> <form action="addPlayer" method="get"> <p>账号<input type="text" name="name"></p> <p>密码<input type="text" name="password"></p> <p>昵称<input type="text" name="nickname"></p> <p>头像: <br/> <input id="photo" type="file"> <%--图片回显--%> <br/> <img id="headImg" style="width: 200px;height: 200px" alt="你还未上传图片"> <br/> <%--进度条--%> <div class="progress"> <div></div> </div> <a id="uploadFile" href="javascript:void(0)" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" >立即上传</a> </p> <p><input type="submit" value="注册"></p> </form> </body> </html>
八、保存完整player信息进入数据库
index.html
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>Title</title> <style> .progress { width: 200px; height: 10px; border: 1px solid #ccc; border-radius: 10px; margin: 10px 0px; overflow: hidden; } /* 初始状态设置进度条宽度为0px */ .progress > div { width: 0px; height: 100%; background-color: yellowgreen; transition: all .3s ease; } </style> <script type="text/javascript" src="js/jquery.min.js"></script> <script type="text/javascript"> $(function(){ $("#uploadFile").click(function(){ // 获取要上传的文件 var photoFile =$("#photo")[0].files[0] if(photoFile==undefined){ alert("您还未选中文件") return; } // 将文件装入FormData对象 var formData =new FormData(); formData.append("headPhoto",photoFile) // ajax向后台发送文件 $.ajax({ type:"post", data:formData, url:"fileUpload.do", processData:false, contentType:false, success:function(result){ // 接收后台响应的信息 alert(result.message) // 图片回显 $("#headImg").attr("src","http://192.168.8.109:8090/upload/"+result.newFileName); // 将文件类型和文件名放入form表单 $("#photoInput").val(result.newFileName) $("#filetypeInput").val(result.filetype) }, xhr: function() { var xhr = new XMLHttpRequest(); //使用XMLHttpRequest.upload监听上传过程,注册progress事件,打印回调函数中的event事件 xhr.upload.addEventListener('progress', function (e) { //loaded代表上传了多少 //total代表总数为多少 var progressRate = (e.loaded / e.total) * 100 + '%'; //通过设置进度条的宽度达到效果 $('.progress > div').css('width', progressRate); }) return xhr; } }) }) }) </script> </head> <body> <form action="addPlayer" method="get"> <p>账号<input type="text" name="name"></p> <p>密码<input type="text" name="password"></p> <p>昵称<input type="text" name="nickname"></p> <p>头像: <br/> <input id="photo" type="file"> <%--图片回显--%> <br/> <img id="headImg" style="width: 200px;height: 200px" alt="你还未上传图片"> <br/> <%--进度条--%> <div class="progress"> <div></div> </div> <a id="uploadFile" href="javascript:void(0)" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" >立即上传</a> <%--使用隐藏的输入框存储文件名称和文件类型--%> <input id="photoInput" type="hidden" name="photo" > <input id="filetypeInput" type="hidden" name="filetype"> </p> <p><input type="submit" value="注册"></p> </form> </body> </html>
FileUploadController代码
见上一步
playerController代码
package com.lanson.controller; import com.lanson.pojo.Player; import com.lanson.service.PlayerService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; /** * @Author: Lansonli * @Description: MircoMessage:Mark_7001 */ @Controller public class PlayerController { @Autowired private PlayerService playerService; @RequestMapping("addPlayer") public String addPlayer(Player player){ // 调用服务层方法,将数据保存进入数据库 playerService.addPlayer(player); // 页面跳转至player信息展示页 return "redirect:/showPlayer.jsp"; } }
Service层代码
package com.lanson.service.impl; import com.lanson.mapper.PlayerMapper; import com.lanson.pojo.Player; import com.lanson.service.PlayerService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; /** * @Author: Lansonli * @Description: MircoMessage:Mark_7001 */ @Service public class PlayerServiceImpl implements PlayerService { @Autowired private PlayerMapper playerMapper; @Override public boolean addPlayer(Player player) { return playerMapper.addPlayer(player)>0; } }
mapper代码
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.lanson.mapper.PlayerMapper"> <insert id="addPlayer"> insert into player values(DEFAULT ,#{name},#{password},#{nickname},#{photo},#{filetype}) </insert> </mapper>
到此这篇关于SpringMVC文件上传中要解决的问题的文章就介绍到这了,更多相关SpringMVC文件上传问题内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!