public class UploadServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
Upfile upfile = new Upfile();
try {
doUpload(request,upfile);
} catch (Exception e) {
e.printStackTrace();
request.setAttribute("message", "上传失败!!");
request.getRequestDispatcher("/message.jsp").forward(request, response);
return;
}
BusinessService service = new BusinessService();
service.addUpfile(upfile);
request.setAttribute("message", "上传成功!!");
request.getRequestDispatcher("/message.jsp").forward(request, response);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
//把表单中的普通输入项的数据保存到map中,把上传文件保存到硬盘中
private void doUpload(HttpServletRequest request, Upfile upfile) throws FileUploadException, IllegalAccessException, InvocationTargetException, IOException{
DiskFileItemFactory factory = new DiskFileItemFactory();
//设置上传文件的临时目录。后面用item.delete()方法删除临时目录里的没用的文件。
String temppath = this.getServletContext().getRealPath("/WEB-INF/temp");
String path = this.getServletContext().getRealPath("/WEB-INF/upload");
//设置临时文件目录一定要放在ServletFileUpload创建之前
factory.setRepository(new File(temppath));
ServletFileUpload upload = new ServletFileUpload(factory);
upload.setHeaderEncoding("UTF-8");
List<FileItem> list = upload.parseRequest(request);
for(FileItem item : list){
if(item.isFormField()){
String name = item.getFieldName(); //username description
String value = item.getString("UTF-8");
BeanUtils.setProperty(upfile, name, value);
}else{
String filename = item.getName();
int pos = filename.lastIndexOf("\\");
if(pos>0){
filename = filename.substring(pos+1);
}
InputStream in = item.getInputStream();
//得到文件写到服务器硬盘哪个目录中
String realpath = makeDir(path,filename);
//得到文件数据写到服务器硬盘的哪个文件中
String realfilename = makeFileName(filename);
//把文件真实名、在硬盘中的名称和文件的保存目录封装到实体中
upfile.setFilename(filename);
upfile.setPath(realpath);
upfile.setRealfilename(realfilename);
FileOutputStream out = new FileOutputStream(realpath + "\\" + realfilename);
byte buffer[] = new byte[1024];
int len = 0;
while((len=in.read(buffer))>0){
out.write(buffer, 0, len);
}
in.close();
out.close();
item.delete();//临时文件删除要在流关闭之后,不然删除不掉,流没有完全关闭的话,会出现占用资源windows系统的问题
upfile.setUptime(new Date());
}
}
}
//打散存储
private String makeDir(String path,String filename){
int hashcode = filename.hashCode();
int dir1 = hashcode&0xf;
int dir2 = (hashcode>>4)&0xf;
String realpath = path + "\\" + dir1 + "\\" + dir2;
File file = new File(realpath);
if(!file.exists()) file.mkdirs();
return realpath;
}
//防止后来上传文件覆盖存在的文件
private String makeFileName(String filename){
int pos = filename.lastIndexOf(".");
String ext = filename.substring(pos);
return UUID.randomUUID().toString() + ext;
}
}
文件上传的细节处理:
1.上传文件名的中文乱码问题
解决方案:调用ServletFileUpload.setHeaderEncoding方法即可
2.上传表单中的普通字段乱码问题
解决方案:获取数据时调用FileItem.getString(charset)方法指定字符集即可
3.服务器安全性问题
解决方案:把上传文件保存到外界无法直接访问到的目录,例如WEB-INF目录中
4.为防止上传文件被覆盖的问题,要保证上传文件的唯一性
解决方案:用UUID算法为每一个上传文件生成一个唯的文件名
5.为防止一个目录下文件过多,影响系统性能,要打散存储上传文件
解决方案:用文件名的hash值,生成对应的文件保存目录
6.临时文件的删除问题
解决方案:在处理完FileItem后,要记得在finally代码块中调用item.delete方法删除临时文件
7.阻止上传非法格式文件
解决方案:获取到上传文件后,栽取文件的后缀名,根据后缀名判断上传文件是否为合法文件
8.监听上传进度
9.在页面里面动态添加文件上传输入项