记录下采用AJAX的方式搭配SpringMVC完成文件上传。
一:关于multipart请求
ajax异步提交、form表单使用action进行post/get提交请求,Content-Type默认都为application/x-www-form-urlencoded。当提交表单时,表单中的“属性-值”对会被拼接成一个字符串:username=admin&sex=nan&age=12
当form表单带图片、视频等二进制数据就要用到multipart表单了,需要指定表单属性为multipart。 multipart表单会把表单分割成块,表单中的每个字段对应一个块,每个块都有自己的数据类型。
二:SpringMVC文件上传代码
实现文件上传,其实就是解析一个Mutipart请求。DispatchServlet自己并不负责去解析mutipart 请求,而是委托一个实现了MultipartResolver接口的类来解析mutipart请求。在Spring3.1之后Spring提供了两个现成的MultipartResolver接口的实现类:CommonMutipartResolver:通过利用Jakarta Commons FileUpload来解析mutipart 请求。
StandardServletMutipartResolver:依赖Servlet3.0来解析mutipart请求。
所以要实现文件上传功能,只需在我们的项目中配置好这两个bean中的任何一个即可。其实这两个都很好用,如果我们部署的容器支持Servlet3.0,我们完全可以使用StandardServletMutipartResolver。但是如果我们的应用部署的容器不支持Servlet3.0或者用到的Spring版本是3.1以前的,那么我们就需要用到CommonMutipartResolver了
通过CommonMutipartResolver 解析mutipart 请求
引入第三方依赖Apache的commons-fileupload第三方类库。<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.2.1</version>
</dependency>
在springMVC的配置文件中注册通过CommonMutipartResolver
<!--配置文件上传的解析类-->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="maxUploadSize" value="100000" />
<property name="maxInMemorySize" value="100000" />
</bean>
编写文件上传的Controller
@Controller
public class FileUpload {
@RequestMapping("/uploadFile")
private @ResponseBody String uploadFile(MultipartFile image, HttpSession session,String name) {
System.out.println(name);
JSONObject jsonObject = new JSONObject();
//判断上传文件是否为空
if (!image.isEmpty()) {
File path = new File(session.getServletContext().getRealPath("img"));//文件存储地
String fileName = image.getOriginalFilename();//原始文件名
if (fileName.endsWith("jpg") || fileName.endsWith("png")) {//限制只能上传jpg和png的图片文件
File file = new File(path, fileName);
if (!file.getParentFile().exists()){
file.getParentFile().mkdirs();
}
try {
image.transferTo(file);
jsonObject.put("info","上传文件成功");
} catch (IOException e) {
e.printStackTrace();
jsonObject.put("info","上传文件失败,请上传.jpg或.png类型的图片");
}
}
}else{
jsonObject.put("info","上传文件为空!");
}
return jsonObject.toString();
}
编写界面
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form id="testForm" enctype="multipart/form-data">
<input type="file" name="image"/><br/>
<input type="text" id="name" name="name"/><br/>
<input type="button" value="提交" id="submit">
</form>
</body>
<script type="text/javascript" src="js/jquery-1.8.1.min.js"></script>
<script>
$(function () {
$("#submit").click(function () {
var formData = new FormData($( "#testForm" )[0]);
$.ajax({
type: "post",
url: "uploadFile",
data: formData,
cache: false,
processData: false,
contentType: false,
dataType: 'json',
success: function (data) {
//如果返回的是json字符串、需要在前台解析为json对象
var object = $.parseJSON(data);
console.log(object);
}
});
});
})
</script>
</html>
运行结果如下:
后台收到name、前台收到json数据、服务器端成功上传文件
程序注意事项与FormData介绍
form表单.serialize()无法序列化二进制文件会报错,当表单中含有文件时可以借助FormData的传输方式,formdata增加了ajax对二进制文件上传的支持MDN对formdata的使用介绍:developer.mozilla.org/zh-CN/docs/…
当使用formdata提交后,ajax的cache、processData、contentType均要设置为false。【此处踩坑】
cache设为false是为了兼容ie8,防止ie8之前版本缓存get请求的处理方式。
在 ajax 中 contentType 设置为 false 是为了避免 JQuery 对其操作,从而失去分界符,而使服务器不能正常解析文件。
processData:要求为Boolean类型的参数,默认为true。默认情况下,发送的数据将被转换为对象(从技术角度来讲并非字符串)以配合默认内容类型"application/x-www-form-urlencoded"。如果要发送DOM树信息或者其他不希望转换的信息,请设置为false。
当设置Content-Type为false时:有分界符、且是随机的
当我们手动指定contentType: 'multipart/form-data',还是不行
相关链接
blog.csdn.net/irokay/arti…
blog.csdn.net/suifeng3051…
juejin.cn/post/684490…
www.jianshu.com/p/380661f02…
segmentfault.com/a/119000000…