数据上传是客户端向服务器端上传数据,客户端向服务器发送的所有请求都属于数据上传。文件上传是数据上传的一种特例,指客户端向服务器上传文件。即将保存在客户端的文件上传一个副本到服务器,并保存在服务器中。
1、上传表单要求
- 文件上传要求客户端提交特殊的请求——multipart请求,即包含多部分数据的请求。必须将<form/>标签的enctype属性值设为“multipart/form-data”,enctype表示encodingType,及编码类型
- 由于客户端上传文件的大小是不确定的,所以http协议规定,文件上传的数据要存放于请求正文中,不能出现在URL地址栏内。也就是说,想要上传文件必须提交POST请求。
- 表单中要有<input type="file" />标签
- 注意:multipart/form-data请求与普通请求不同
2、下载文件上传jar包并查看官方文档
- 打开Apache官网http://www.apache.org/,选择APACHE PROJECT LIST中的Commons
- 选择Commons中的FileUpload项目,并下载jar包和源文件
- 查看FileUpload的工作方式
- 查看FileUpload项目的API
3、使用第三方jar包上传文件
public class RegisterServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
public RegisterServlet() {
super();
}
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.getWriter().append("Served at: ").append(request.getContextPath());
}
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//第一步、判断请求是否为multipart请求
if(!ServletFileUpload.isMultipartContent(request)) {
throw new RuntimeException("当前请求只支持文件上传");
}
try {
//第二步、创建FileItem工厂
DiskFileItemFactory factory = new DiskFileItemFactory();
//设置临时文件存储目录
String path = this.getServletContext().getRealPath("/Temp");
File temp = new File(path);
factory.setRepository(temp);
//单位:字节。本例设置边界值为2MB,超过该值会创建临时文件
factory.setSizeThreshold(1024*1024*2);
//第三步、创建文件上传核心组件
ServletFileUpload upload = new ServletFileUpload(factory);
//设置item的头部字符编码,解决中文乱码问题
upload.setHeaderEncoding("utf-8");
//设置单个上传文件的最大值为5MB
upload.setFileSizeMax(1024*1024*5);
//设置一次上传所有文件总和的最大值为10MB(上传多个文件时起作用)
upload.setFileSizeMax(1024*1024*10);
//第四步、解析请求获取所有的item
List<FileItem> items = upload.parseRequest(request);
//第五步、遍历item
for(FileItem item:items) {
if (item.isFormField()) {
processFormField(item);
} else {
processUploadedFile(item);
}
}
} catch (FileUploadException e) {
e.printStackTrace();
}
}
private void processFormField(FileItem item) {
try {
String name = item.getFieldName();
//解决中文乱码问题
String value = item.getString("utf-8");
System.out.println(name+"="+value);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
private void processUploadedFile(FileItem item) {
try {
InputStream inputStream = item.getInputStream();
String fieldName = item.getFieldName();
//获取上传文件原始名称
String fileName = item.getName();
//解决文件同名问题
fileName = System.currentTimeMillis()+fileName;
String contentType = item.getContentType();
boolean isInMemory = item.isInMemory();
long sizeInBytes = item.getSize();
String path = this.getServletContext().getRealPath("/UploadContent");
//Date now = new Date();
Calendar now = Calendar.getInstance();
//对上传的文件进行分类管理
path += "/"+now.get(Calendar.YEAR)+"/"+(now.get(Calendar.MONTH)+1)+"/"+now.get(Calendar.DAY_OF_MONTH);
//若目录不存在,则创建该目录
File directory = new File(path);
if(!directory.exists()) {
directory.mkdirs();
}
File descFile = new File(path,fileName);
OutputStream outputStream = new FileOutputStream(descFile);
int length = -1;
byte[] buffer = new byte[1024];
while((length=inputStream.read(buffer))!=-1) {
outputStream.write(buffer, 0, length);
}
outputStream.close();
inputStream.close();
//删除临时文件
item.delete();
} catch (IOException e) {
e.printStackTrace();
}
}
}