SpringBoot实现文件以及表单数据的上传
一、前期准备
yml文件
spring:
servlet:
multipart:
max-file-size: 10MB #文件上传的最大大小
file-size-threshold: 10MB
pom文件
<!--文件的上传下载-->
<!-- https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload -->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.4</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.4</version>
</dependency>
二、前端页面
通过表单传递图片文件的同时上传表单中的数据
<form method="post" class="form-x" enctype="multipart/form-data" id="registerForm">
<!--教练-->
<div class="form-group">
<div class="label">
<label>球队名称:</label>
</div>
<div class="field">
<input id="teamName" type="text" class="input w50" value="" name="name"
placeholder="请输入4-6位汉字"/>
<div class=""><span style="margin-left: 30px;color:red" hidden="hidden"
id="warn"></span></div>
</div>
</div>
<!--球队队标-->
<div class="form-group">
<div class="label">
<label>球队队标:</label>
</div>
<div class="field">
<input id="teamLog" type="file" accept="image/png, image/jpeg" name="file"
class="input tips" style="width:25%; float:left;" placeholder="仅支持png或jpg格式"
value=""/>
</div>
</div>
<!--球队简介-->
<div class="form-group">
<div class="label">
<label>球队简介:</label>
</div>
<div class="field">
<textarea id="teamIntroduce" class="input" name="intro" style=" height:90px;"
placeholder="请介绍一下自己球队"></textarea>
<div class="tips"></div>
</div>
</div>
<!--球队教练-->
<div class="form-group">
<div class="label">
<label>球队教练:</label>
</div>
<div class="field">
<input id="coachName" type="text" class="input w50" name="coach" value=""/>
<div class="tips"></div>
</div>
</div>
<!--队伍人数-->
<div class="form-group">
<div class="label">
<label>队伍人数:</label>
</div>
<div class="field">
<input id="memberNumber" type="text" class="input w50" name="memberNumber" value=""
placeholder="球队建队人数不能低于12人"/>
<div class="tips"></div>
</div>
</div>
<div class="form-group">
<div class="label">
<label></label>
</div>
<div class="field">
<div style="padding:30px;">
<input type="button" class="button button-block bg-main text-big input-big" onclick="clickMe();"
id="apply-button"
value="申请">
</div>
</div>
</div>
</form>
效果图
使用Ajax提交表单到后台
重点是使用了jQuery使用FormData对象上传文件。
FormData的主要用途有两个:
1、将form表单元素的name与value进行组合,实现表单数据的序列化,从而减少表单元素的拼接,提高工作效率。
2、异步上传文件
创建一个空对象:
var formdata=new FormData(); //通过FormData构造函数创建一个空对象
formdata.append("name","laotie"); //可以通过append()方法来追加数据
console.log(formdata.get("name")); //通过get方法对值进行读取 laotie
formdata.set("name","laoliu"); //通过set方法对值进行设置
console.log(formdata.get("name")); //laoliu
更多详细 参见 https://developer.mozilla.org/zh-CN/docs/Web/API/FormData
可能出现的问题
sp报Unsupported Media Type Content type '*/*;charset=UTF-8' not supported
ajax默认:Content-Type: application/x-www-form-urlencoded;charset=utf-8
解决:前端ajax提交json数据时 contentType:application/json
JS代码
<script>
function clickMe() {
var form = document.getElementById("registerForm"),//先获到表单的JQ对象
formData = new FormData(form);
$.ajax({
url: "/teamRegister",
type: "post",
data: formData,
processData: false,
contentType: false, //contentType设置为false。因为是由<form>表单构造的FormData对象,且已经声明了属性enctype="multipart/form-data",所以这里设置为false。
success: function (data) {
alert("success!!")
},
error: function () {
alert("failure!!")
}
})
}
</script>
表单中的提交方式要设置为post 必须添加 enctype="multipart/form-data"
例如 <form method="post" enctype="multipart/form-data">
input框中的name属性必不可少,要不然传递不到后台,并且应该与实体类的字段保持一致才能自动的封装为JavaBean对象
后台需要接收前台的数据,直接与前台的name属性值保持一致即可
// jq里ajax的processData为true时(默认),不能序列化对象,将直接以data的形式传入,为false时,data序列化
// 成可传输储存的状态,在这里设成false表示将data数据序列化传输,函数视图可以获取数据,如果在默认为true的情况
// 下,函数视图获取不到数据
三、后端代码
@Controller
public class TeamController {
@Autowired
private TeamImageServiceImpl teamImageService;
@Autowired
private ITeamService teamService;
@Autowired
private ITeamIntroduceService teamIntroduceService;
@RequestMapping(value = "/teamRegister")
@ResponseBody
public Map<String, Object> register(Team team, @RequestParam("intro") String intro, @RequestParam("file") MultipartFile file) throws IOException {
Map<String, Object> map = new HashMap<>();
String teamName = team.getName();//获取前端传递的队伍名称
String randomNumber = UUID.randomUUID().toString().replace("-", "");//使用UUID生成唯一标识
//创建一个唯一标识作为评论的主键以及队伍的一个字段,方便用来保存数据将队伍与队伍描述建立起关系
String oldFilename = file.getOriginalFilename(); //获取文件的原始名
String extension = FilenameUtils.getExtension(file.getOriginalFilename());//使用FilenameUtils获得文件的后缀(先导依赖Commons-fileUpload)
String newFileName = teamName + randomNumber + "." + extension; //生成新的文件名(队伍名+随机数+后缀名)
String fileUploadDir = ResourceUtils.getURL("classpath:").getPath() + "/static/teamImages"; //使用ResourceUtils类路径再获取文件保存的路径
String namespace = fileUploadDir + newFileName; //队标的全路径(从盘符开始)
String relativePath = "/static/teamImages" + newFileName; //文件保存的相对路径
team.setUuidNumber(randomNumber);
team.setImgPath(relativePath);
File dateDir = new File(fileUploadDir);
if (!dateDir.exists()) {
dateDir.mkdirs();//判断目录是否存在,不存在则直接创建
}
file.transferTo(new File(fileUploadDir, newFileName));
TeamImage teamImage = new TeamImage(oldFilename, newFileName, relativePath, extension, new Date());
teamService.saveTeam(team);//保存team对象
teamImage.setTeam(team); //teamImage保存team
teamImageService.saveTeamImage(teamImage); //保存teamImage
TeamIntroduce introduce = new TeamIntroduce(randomNumber, team.getId(), intro);
teamIntroduceService.saveTeamIntroduce(introduce);
return map;
}
}
效果
MySQL数据库
MongoDB
可能出现的错误
报错Required String parameter ‘xxxx’ is not present
基本上就是前端的数据并没有成功的传递过来,而后端又用@RequestParam(value="name")来接收考虑前端name属性与@RequestParam的参数是否一致
如果前端传入的是json数据那么后端使用
@RequestBody HashMap<String, String> map
进行接收,然后再通过map.get(“name”)获取对应的数据
如果前端传入的是正常表单数据,那么后端使用
@RequestParam("name") String name 或者
@RequestParam(value="name", required = false) String name接收参数
需要注意的是,如果请求类型为delete并且参数类型不是json的话,不能使用通过表单类型提交,参数需要跟到请求url后面,并且后台使用@PathVariable进行获取参数