FormData 简介
- FormData 是 Html5 新加进来的一个类,可以模拟表单数据
- 利用 FormData 对象,可以通过JavaScript键值对来模拟一系列表单控件
- 可以使用 JQuery 的 $.Ajax 结合 FormData 异步上传二进制文件
- 可以先通过 new 关键字创建一个空的 FormData 对象,然后使用 append() 方法向该对象里添加字段(字段的值可以是一个 File对象或者字符串,剩下其他类型的值都会被自动转换成字符串)
- 也可以 new 的同时直接传入表单对象,从而创建有值的FormData对象
实现文件上传
环境搭建
引用下面两个jar包,可以去maven中央仓库下载
jsp界面
//创建一个表单,注意提交方法一定是:"post" 表单数据编码格式一定是:"multipart/form-data" 表内字段一定要有name属性
<form id="uploadForm" method="post" enctype="multipart/form-data">
用户名: <input type="text" name="userName"><br>
头 像: <input type="file" name="userPic"><br>
<input type="button" id="upload_Btn" value="提交">
</form>
使用ajax提交
$("#uploadBtn").click(function () {
var formdata=new FormData($("#uploadForm")[0]); //新建formdata对象,并传入表单
$.ajax({
url:"upload", //请求地址
type:"POST", //提交方式
data:formdata, //数据
sync:false, //异步提交
cache:false, //不读缓存
contentType:false, //不做格式处理
processData:false,//不序列化
success:function (result) {
console.log(result);
},
error:function (error) {
console.log("error:"+error);
}
})
})
Servlet实现
// 检测是否为多媒体上传
if (!ServletFileUpload.isMultipartContent(request)) {
// 如果不是则停止
PrintWriter writer = response.getWriter();
writer.println("Error: 表单必须包含 enctype=multipart/form-data");
writer.flush();
return;
}
// 构造临时路径来存储上传的文件
// 这个路径相对当前应用的目录
String uploadPath = getServletContext().getRealPath("/") + File.separator + "upload";
// 如果目录不存在则创建
File uploadDir = new File(uploadPath);
if (!uploadDir.exists()) {
uploadDir.mkdir();
}
//1、创建一个DiskFileItemFactory工厂
DiskFileItemFactory factory = new DiskFileItemFactory();
//2、创建一个文件上传解析器
ServletFileUpload upload = new ServletFileUpload(factory);
//3、解决上传文件名的中文乱码
upload.setHeaderEncoding("UTF-8");
try {
// 解析请求的内容提取文件数据
@SuppressWarnings("unchecked")
List<FileItem> formItems = upload.parseRequest(request);
if (fileItems != null && fileItems.size() > 0) {
for(FileItem item:fileItems){
//如果fileitem中封装的不是普通输入项的数据
if(!item.isFormField()){
//字段名称
String fieldName = item.getFieldName(); //文件对应字段名称,就是input中name的值
//文件 XXX.doc
String fileName = item.getName();
//获取文件后缀名
String suffix = fileName.substring( fileName.lastIndexOf( '.' ) ); //.doc
//获取时间戳作为文件名
long id = new Date().getTime();
//构建文件路径
String fileUrl= uploadPath + File.separator + id+File.separator+suffix ;
//新建文件
File file = new File( fileUrl );
try {
//文件写入
item.write( file );
} catch (Exception e) {
e.printStackTrace();
}
/**
* 图片访问地址:
* http://XXX:8080/javaewb/img/id+suffix
*/
}else {
//普通字段
String fieldName = item.getFieldName();
String value = item.getString("UTF-8");
System.out.println(fieldName +"->"+value);
}
}
} catch (FileUploadException e) {
e.printStackTrace();
}
注意
-
为保证服务器安全,上传文件应该放在外界无法直接访问的目录下,比如放于WEB-INF目录下。
-
为防止文件覆盖的现象发生,要为上传文件产生一个唯一的文件名。
-
为防止一个目录下面出现太多文件,要使用hash算法打散存储。
-
要限制上传文件的最大值。
-
要限制上传文件的类型,在收到上传文件名时,判断后缀名是否合法。