用apache文件上传组件commons-io-2.4.jar commons-fileupload-1.2.1.jar进行文件上传

package cn.lfd.web.controller;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.UUID;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadBase;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
//利用apache文件上传组件进行文件上传
public class UploadServlet extends HttpServlet {

	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		String savepath = this.getServletContext().getRealPath("/WEB-INF/upload");//得到WEB-INF/upload代表的真实路径
		
		try {
			DiskFileItemFactory factory = new DiskFileItemFactory();//得到工厂
			
			//若文件超过factory默认的缓冲大小10kb,指定一个临时文件夹,系统会先把文件上传到临时文件夹,再上传到/WEB-INF目录
			factory.setRepository(new File(this.getServletContext().getRealPath("/WEB-INF/temp")));
			
			ServletFileUpload upload = new ServletFileUpload(factory);
			if(!upload.isMultipartContent(request)) {
				//按传统方式获取request.getParameter(name);
				return;
			}
			
			//upload.setFileSizeMax(1024);//设置上传的文件大小不超过1kb
			//upload.setSizeMax(1024*16);//设置多个文件上传项上传的大小不超过16kb
			
			upload.setHeaderEncoding("UTF-8");//设置upload的编码,防止上传的中文文件名乱码
			List fileitems = upload.parseRequest(request);//利用upload解析request得到一个FileItem集合
			
			for(FileItem fileitem:fileitems) {
				if(fileitem.isFormField()) {//如果是普通输入项,按以下方式获取
					
					String name = fileitem.getFieldName();
					String value = fileitem.getString("UTF-8");//防止普通输入项的中文乱码
					//value = new String(value.getBytes("ISO-8859-1"),"UTF-8");防止中文乱码也可用这个方法
					
					System.out.println(name+"="+value);
				}else {//不是普通输入项,用以下方式获取
					String filename = fileitem.getName();//得到上传的文件名
					filename = filename.substring(filename.lastIndexOf("\\")+1);//有的浏览器上传的是绝对路径,这里我们必须做一个截取,取出文件名
					filename = makefilename(filename);//利用UUID算法生成一个唯一的文件名,防止提交的文件重名而被覆盖
					
					String realsavepath = makepath(filename, savepath);//利用hashcode算法生成一个随机目录来保存文件,使一个目录的文件不容易超过1000个,提升文件访问效率
					InputStream in = fileitem.getInputStream();//得到输入流
					
					//最后用文件输出流把文件写到生成的目录
					FileOutputStream out = new FileOutputStream(realsavepath+"\\"+filename);
					byte[] flush = new byte[1024];
					int len = 0;
					while(-1!=(in.read(flush))) {
						out.write(flush);
					}
					in.close();//关闭流
					out.close();
					fileitem.delete();
				}
			}
			
		}catch (FileUploadBase.FileSizeLimitExceededException e) {
			e.printStackTrace();//单个文件超出设置的大小会抛出这个异常
		}catch (FileUploadBase.SizeLimitExceededException e) {
			e.printStackTrace();//多个文件加起来的大小超过设置的大小会抛出这个异常
		}catch (FileUploadException e) {
			e.printStackTrace();
		}
	}

	public String makefilename(String filename) {//UUID生成唯一文件名
		return UUID.randomUUID().toString()+"_"+filename;
	}
	
	public String makepath(String filename,String savepath) {//hashcode算法打散上传的文件
		int hashcode = filename.hashCode();
		
		int dir1 = hashcode&0xf;//dir1的大小为0-15
		int dir2 = (hashcode&0xf0)>>4;//di2的大小为0-15
		
		String dir = savepath +"\\"+dir1+"\\"+dir2;//构建出这个路径
		File file = new File(dir);//利用File对象创建出这个文件夹
		if(!file.exists()) {
			file.mkdirs();
		}
		return dir;
	}
	
	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		doGet(request, response);
	}

}
注意事项:
1.上传文件名乱码问题:
upload.setHeaderEncoding("UTF-8");
 1.1普通输入项中文乱码(两种方法)
 String value = fileitem.getString("UTF-8");
 value = new String(value.getBytes("ISO-8859-1"),"UTF-8");
2.为保证服务器安全,上传文件应放到外界无法访问的目录
3.为防止文件覆盖的发生,要为每一个文件产生一个唯一的文件名
4.防止上传文件保存目录超过一千个文件,用hash算法打散
5.限制上传文件的大小可以用
 upload.setFileSizeMax(1024);//单个文件限制大小
 upload.setSizeMax(1024*16);//多个文件一起限制大小
 超过大小用抛出FileUploadBase.FileSizeLimitExceededException异常提示用户
6.确保临时文件被删除,一定要在处理完上传文件后,调用fileitem.delete()方法
7.限制文件的上传类型可以通过判断文件的后缀名实现

你可能感兴趣的:(文件上传与下载)