上传文件的表单项
建立一个表单,有三个域分别是username,age,photo。其中photo是上传文件的域,其type属性是file。
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<title>上传照片</title>
</head>
<body>
<form action=" <c:url value="/upload"></c:url> " method="post" enctype="multipart/form-data">
用户名:<input type="text" name="username"><br>
年龄:<input type="text" name="age"><br>
上传照片<input type="file" name="photo">
<input type="submit" name="sub" value="提交">
</form>
</body>
</html>
其中最需要注意的是enctype属性,该属性默认值是application/x-www-form-urlencoded,如果需要上传文件必须修改为multipart/form-data。
HTTP请求
请求头
Content-Type:multipart/form-data是在表单的enctype里设置的。
分号后面还有一个boundary=…后面跟的是一段用来分割表单域的字符串,后面就会见到它。
请求体
上传文件只能使用POST,现在查看一下请求体:
仔细看表单的四个域分别被一段字符串分割,这段字符串就是在Content-Type中boundary定义的。
请求体的格式是有规律的,在请求到达服务器后,服务器必须根据这些过滤从请求体中解析出对应的域和值。
也就是说request.getParameter()对于multipart/form-data类型的表单是没有用的。
commons-fileupload
不用担心,解析表单域的工作已经有人做好了,我们并不用重复的造轮子。
@WebServlet(name = "UploadServlet",urlPatterns = "/upload")
public class UploadServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//创建一个实例化工厂
DiskFileItemFactory diskFileItemFactory = new DiskFileItemFactory();
diskFileItemFactory.setSizeThreshold(1024*500);//设置缓冲内存大小
//创建一个保存临时文件的目录
File tmpDir = new File(getServletContext().getRealPath(""), "WEB-INF/tmp");
if(!tmpDir.exists()){
tmpDir.mkdirs();
}
//设置临时文件目录
diskFileItemFactory.setRepository(tmpDir);
ServletFileUpload servletFileUpload = new ServletFileUpload(diskFileItemFactory);
servletFileUpload.setFileSizeMax(1024*1024*10);//设置上传文件的大小为10M
servletFileUpload.setHeaderEncoding("utf-8");//设置字符编码
//最重要的来了,解析请求
try {
List<FileItem> itemList = servletFileUpload.parseRequest(request);
//打印名字和年龄
System.out.println(itemList.get(0).getFieldName()+":"+itemList.get(0).getString("utf-8"));
System.out.println(itemList.get(1).getFieldName()+":"+itemList.get(1).getString("utf-8"));
//创建保存上传文件的目录
File uploadsDir = new File(getServletContext().getRealPath(""), "WEB-INF/uploads");
if(!uploadsDir.exists()){
uploadsDir.mkdirs();
}
//获得文件名
String fileName = itemList.get(2).getName();
//因为有的浏览器上传文件的文件名包含文件在客户端的路径,所以需要特殊处理
int index = fileName.lastIndexOf("\\");
if(index!=-1){
fileName = fileName.substring(index);
}
//架上uuid防止文件重名
fileName=UUID.randomUUID()+"_"+fileName;
itemList.get(2).write(new File(uploadsDir,fileName));
} catch (FileUploadException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
}