文章目录
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博客🙉
- 📢停下休息的时候不要忘了别人还在奔跑,希望大家抓紧时间学习,全力奔赴更美好的生活✨
转载:https://blog.csdn.net/xiaoweite1/article/details/128645143
查看评论