文件上传的限制
1.上传对表单限制
>method必须为post
>enctype="multipart/form-data":表示多部件表单数据
>表单中需要添加文件表单项:<input type="file" name="" />
2.上传对Servlet的限制
>ServletInputStream request.getInputStream(); 包含整个请求体
<form action="${pageContext.request.contextPath }/FileUploadServlet" method="post" enctype="multipart/form-data">
用户名:<input type="text" name="username"/><br/>
文件1:<input type="file" name="file1"/><br/>
文件2:<input type="file" name="file2"/><br/>
<input type="submit" value="提交"/>
</form>
在jsp页面中,尝试在提交表单中存放普通文本和文件上传。当提交之后,在HttpWatch中抓包可以看出,客户端发送给服务器的信息如下:
普通文本表单可以不设置enctype属性:
>当method="post"时,enctype的默认值为application/x-www-form-urlencoded,表示使用url编码正文
>当method="get"时,enctype的默认值为null,没有正文,就不需要enctype
通过httpWatch测试,查看表单的请求数据正文,我们发现请求中只有文件名称,而没有文件内容。也就是说,当表单的enctype不是multipart/form-data时,请求中不包含文件内容,而只有文件的名称,这说明普通文本表单中input:file与input:text没什么区别了。
通过httpWatch测试,查看表单的请求数据正文部分,发现正文部分是由多个部件组成,每个部件对应一个表单字段,每个部件都有自己的头信息。头信息下面是空行,空行下面是字段的正文部分。多个部件之间使用随机生成的分隔线隔开。
文本字段的头信息中只包含一条头信息,即Content-Disposition,这个头信息的值有两个部分,第一部分是固定的,即form-data,第二部分为字段的名称。在空行后面就是正文部分了,正文部分就是在文本框中填写的内容。
文件字段的头信息中包含两条头信息,Content-Disposition和Content-Type。Content-Disposition中多出一个filename,它指定的是上传的文件名称。而Content-Type指定的是上传文件的类型。文件字段的正文部分就是文件的内容。
因为我们上传的文件都是普通文本文件,即txt文件,所以在httpWatch中是可以正常显示的,如果上传的是exe、mp3等文件,那么在httpWatch看到的就是乱码了。
Commons-fileupload(commons-fileupload.jar commons-io.jar)
该包会解析request中的上传数据(包括各种请求头的和相应的值),解析后的结果是将表单封装到一个FileItem对象中,只需要调用FileItem的方法就能够获取信息。
上传步骤:
1>创建工厂:DiskFileItemFactory factory = new DiskFileItemFactory();
2>创建解析器:ServletFileUpload sfu = new ServletFileUpload(factory);
3>使用解析器来解析request,得到FileItem集合:List<FileItem> fileItemList = sfu.parseRequest(request);
FileItem对象中的方法
>boolean isFormField():是否为普通表单项,如果返回true则为普通表单项,返回falst则为文件表单项
>String getFieldName():返回当前表单项的名称
>String getString(String charset):返回表单项的值(仅是普通表单项时使用)
>String getName():返回上传文件的名称
>long getSize():返回上传文件字节数
>InputStream getInputStream():返回上传文件对应的输入流
>void write(File destFile):把上传文件的内容放在指定的文件中
DiskFileItemFactory factory = new DiskFileItemFactory();
ServletFileUpload sfu = new ServletFileUpload(factory);
try {
List<FileItem> fileItemList = sfu.parseRequest(request);
FileItem fi1 = fileItemList.get(0);
FileItem fi2 = fileItemList.get(1);
System.out.println("普通表单项演示:"+fi1.getFieldName()+"="+fi1.getString("UTF-8"));
System.out.println("Content-type:"+fi2.getContentType());
System.out.println("Size:"+fi2.getSize());
System.out.println("filename:"+fi2.getName());
//保存文件
File destFile = new File("e:/applicationForm.doc");
try {
fi2.write(destFile);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} catch (FileUploadException e) {
// TODO Auto-generated catch block
throw new RuntimeException(e);
}
}
<form action="<c:url value='/UpLoadServlet'/>" method="post" enctype="multipart/form-data">
用户名:<input type="text" name="username"/><br/>
家庭经济困难学生认定申请表上传:<input type="file" name="ApplicationForm"/><br/>
<input type="submit" value="提交"/>
</form>
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
DiskFileItemFactory dfif = new DiskFileItemFactory(1024*20, new File("F:\\temp"));
ServletFileUpload fileUpload = new ServletFileUpload(dfif);
try {
List<FileItem> list = fileUpload.parseRequest(request);
FileItem fileItem = list.get(1);
String name = fileItem.getName();
String savepath = this.getServletContext().getRealPath("/WEB-INF/uploads");
// 保存文件
fileItem.write(path(savepath, name));
} catch (Exception e) {
throw new ServletException(e);
}
}
private File path(String savepath, String filename) {
// 从完整路径中获取文件名称
int lastIndex = filename.lastIndexOf("\\");
if(lastIndex != -1) {
filename = filename.substring(lastIndex + 1);
}
// 通过文件名称生成一级、二级目录
int hCode = filename.hashCode();
String dir1 = Integer.toHexString(hCode & 0xF);
String dir2 = Integer.toHexString(hCode >>> 4 & 0xF);
savepath = savepath + "/" + dir1 + "/" + dir2;
// 创建目录
new File(savepath).mkdirs();
// 给文件名称添加uuid前缀
String uuid = CommonUtils.uuid();
filename = uuid + "_" + filename;
// 创建文件完成路径
return new File(savepath, filename);
}
下载