这个小组件,它会帮我们解析request中的上传数据,解析后的结果是一个表单项数据封装到一个FileItem对象中。我们只需要调用FileItem的方法即可。
Maven依赖
commons-fileupload
commons-fileupload
1.3.2
相关类
工厂:DiskFileItemFactory
解析器:ServletFileUpload
表单项:FileItem
上传三大步
创建工厂:DiskFileItemFactory factory = new DiskFileItemFactory();
创建解析器:ServletFileUpload sfu = new ServletFileUpload(factory);
使用解析器解析request:List fileItemList = sfu.parseRequest(request);
FileItem API
boolean isFormField();// 是否为普通表单项!返回true为普通表单项,如果为false即文件表单项!
String getFieldName();// 返回当前表单项的名称;
String getString(String charset);// 返回表单项的值;
String getName();// 返回上传的文件名称
long getSize();// 返回上传文件的字节数
InputStream getInputStream();// 返回上传文件对应的输入流
void write(File destFile);// 把上传的文件内容保存到指定的文件中。
String getContentType();
需要注意的一些上传细节
保存地址
上传到服务器的地址最好是在WEB-INF下,因为这个目录浏览器是访问不到的
文件名称相关问题
有的浏览器上传的文件名是绝对路径,这需要切割!C:\files\baibing.jpg
String filename = fi2.getName();
int index = filename.lastIndexOf("\\");
if(index != -1) {
filename = filename.substring(index+1);
}
文件名乱码或者普通表单项乱码:request.setCharacterEncoding("utf-8");因为fileupload内部会调用request.getCharacterEncoding(); > request.setCharacterEncoding("utf-8");//优先级低servletFileUpload.setHeaderEncoding("utf-8");//优先级高
文件同名问题;我们需要为每个文件添加名称前缀,这个前缀要保证不能重复。uuid > filename = CommonUtils.uuid() + "_" + filename;
目录打散
不能在一个目录下存放之多文件:
首字符打散:使用文件的首字母做为目录名称,例如:abc.txt,那么我们把文件保存到a目录下。如果a目录这时不存在,那么创建之;
时间打散:使用当前日期做为目录;
哈希打散:1. 通过文件名称得到int值,即调用hashCode();2. 它int值转换成16进制0~9, A~F;3. 获取16进制的前两位用来生成目录,目录为二层!例如:1B2C3D4E5Fÿ