SpringMVC:SpringMVC文件上传中要解决的问题
Posted Lansonli
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SpringMVC: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)">立即上传</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)">立即上传</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)">立即上传</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)">立即上传</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://lansonli.blog.csdn.net
- 📢欢迎点赞 👍 收藏 ⭐留言 📝 如有错误敬请指正!
- 📢本文由 Lansonli 原创,首发于 CSDN博客🙉
- 📢停下休息的时候不要忘了别人还在奔跑,希望大家抓紧时间学习,全力奔赴更美好的生活✨
以上是关于SpringMVC:SpringMVC文件上传中要解决的问题的主要内容,如果未能解决你的问题,请参考以下文章