JavaWeb课程系列
第17章文件上传下载
1.文件上传
1.1提出问题
客户需要将自己的文件上传给服务器怎么处理?
文件上传的时候是怎样提交给服务器的?
答:我们可以使用multipart/form-data表单处理文件上传
文件的上传是以流的形式提交给服务器的
1.2文件上传步骤
文件上传我们需要用到两个包。commons-fileupload-1.3.1.jar、commons-io-2.4.jar。
所以先导入包。然后进行文件上传测试
文件上传步骤:
1)修改表单enctype值为multipart/form-data,并且method=post
<form action="upload" method="post" enctype="multipart/form-data">
<input type="file" name="file">
<input type="submit">
</form>
2)创建文件上传请求解析器
在doPost方法中创建ServletFileUpload对象,并传入DiskFileItemFactory工厂对象
DiskFileItemFactory factory = new DiskFileItemFactory();
ServletFileUpload fileUpload = new ServletFileUpload(factory);
3)解析并上传文件
解析上传文件请求
List<FileItem> list = fileUpload.parseRequest(request);
for(FileItem f : list){
if(f.isFormField()){//普通表单项
}else{ //文件表单项
String name = f.getName();
System.out.println(name);
f.write(new File("D:/"+name));
}
}
注意事项:
①、当文件上传表单的文件项未选择文件时,文件大小为0,应该做判断,当文件大小为0则不进行上传
②、使用fileItem.getName()获取文件名。在火狐谷歌下,为文件的名字。在ie下为文件的路径,因此要获取文件名需要进行处理
③、使用fileItem.getString(“utf-8”),获取文件普通表单项的值
完整的文件上传代码:
protected void doPost(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException {
// 1、创建fileItem工厂
DiskFileItemFactory factory = new DiskFileItemFactory();
// 2、创建文件上传对象
ServletFileUpload fileUpload = new ServletFileUpload(factory);
// 3、解析文件上传请求
try {
List<FileItem> list = fileUpload.parseRequest(request);
// 4、遍历解析出的每个FileItem文件
for (FileItem f : list) {
// 这是普通表单项
if (f.isFormField()) {
// 表单项的name值
String fieldName = f.getFieldName();
// 表单项value,使用编码取得中文
String fieldValue = f.getString("utf-8");
System.out.println(fieldName + ":" + fieldValue);
// 表示文件表单项
} else {
//获取文件大小,有可能并没有上传文件
long size = f.getSize();
if(size == 0){
continue;
}
// 获取文件名字
String name = f.getName();
// ie下是全路径,火狐谷歌为文件名,需要不同处理
if (name.contains("\\")) {
name = name.substring(name.lastIndexOf("\\") + 1);
}
//获取文件保存的服务端路径
String realPath = request.getServletContext().getRealPath("/upload");
File file = new File(realPath);
if(!file.exists()){
file.mkdirs();
}
//生成一个唯一不重复的文件名
name = UUID.randomUUID().toString().replace("-", "")+"-"+name;
//将文件内容写入
f.write(new File(realPath+"/"+name));
}
}
} catch (FileUploadException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
response.setContentType("text/html;charset=UTF-8");
response.getWriter().write("上传完成!");
}
其他注意:
fileUpload可以来限制文件的大小
//设置当文件的大小为50KB
//fileUpload.setFileSizeMax(1024*50);
//设置多个文件的总大小为150KB
fileUpload.setSizeMax(1024*150);
当文件超出大小限制的时候会抛出异常,增加catch子句来处理
catch (SizeLimitExceededException e) {
response.setContentType("text/html;charset=UTF-8");
response.getWriter().write("文件大小超出限制");
return;
}
原理:
分析文件上传的请求我们会发现,文件上传的时候request的body会增加一个分界符,分界符用来分割正常的表单域和文件表单域,文件的内容在分界符的中间,以流的形式传递,文件上传的request请求如下:
以上是请求头;
下面是请求体携带的数据: