SpringMVC文件上传中要解决的问题大汇总

作者:Lansonli 时间:2023-09-02 06:09:20 

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对文件名进行重命名。

SpringMVC文件上传中要解决的问题大汇总

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>

七、单独准备文件存储服务器

分服务器上传作用

  • 数据库服务器:运行我们的数据库

  • 缓存和消息服务器:负责处理大并发访问的缓存和消息

  • 文件服务器:负责存储用户上传文件的服务器。

  • 应用服务器:负责部署我们的应用

在实际开发中,我们会有很多处理不同功能的服务器。(注意:此处说的不是服务器集群)

总结:分服务器处理的目的是让服务器各司其职,从而提高我们项目的运行效率。

分服务器工作示意图

SpringMVC文件上传中要解决的问题大汇总

单独解压一个Tomcat作为文件服务器

SpringMVC文件上传中要解决的问题大汇总

设置远程服务器端口号 

SpringMVC文件上传中要解决的问题大汇总

SpringMVC文件上传中要解决的问题大汇总

远程服务器中设置非只读

SpringMVC文件上传中要解决的问题大汇总

webapps下创建一个upload目录

SpringMVC文件上传中要解决的问题大汇总

启动测试

SpringMVC文件上传中要解决的问题大汇总

项目中导入依赖

<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>

来源:https://blog.csdn.net/xiaoweite1/article/details/128645143

标签:SpringMVC,文件,上传
0
投稿

猜你喜欢

  • springboot redis分布式锁代码实例

    2023-12-05 21:40:10
  • 解析maven的用法和几个常用的命令(推荐)

    2022-04-16 23:31:15
  • 深入理解Java Socket通信

    2022-10-03 04:56:10
  • C#编程实现自定义热键的方法

    2023-12-05 23:57:18
  • Springboot Vue可配置调度任务实现示例详解

    2023-11-09 03:33:19
  • C#编程实现动态改变配置文件信息的方法

    2022-05-01 15:09:25
  • Android开发中MotionEvent坐标获取方法分析

    2022-03-29 02:43:42
  • java实现将结果集封装到List中的方法

    2021-10-27 22:29:45
  • Android自定义View实现分段选择按钮的实现代码

    2022-09-06 07:46:21
  • 谈谈Java类型中ParameterizedType,GenericArrayType,TypeVariabl,WildcardType

    2022-10-18 17:43:07
  • Android仿直播类app赠送礼物功能

    2023-07-26 05:06:17
  • Java实现map转换成json的方法详解

    2022-09-09 12:26:03
  • Android ListView仿微信聊天界面

    2023-10-15 04:59:46
  • android调用国家气象局天气预报接口json数据格式解释

    2022-09-16 21:08:24
  • 基于Java ActiveMQ的实例讲解

    2023-08-24 08:39:38
  • SpringCloud Function SpEL注入漏洞分析及环境搭建

    2022-07-03 05:18:21
  • Windows下Flutter+Idea环境搭建及配置

    2022-01-22 18:12:13
  • Android开发笔记之:Handler Runnable与Thread的区别详解

    2023-11-10 12:29:01
  • 在IDEA使用中directory和package的操作

    2022-07-05 22:05:53
  • C#实现HSL颜色值转换为RGB的方法

    2022-02-21 09:56:11
  • asp之家 软件编程 m.aspxhome.com