zoukankan      html  css  js  c++  java
  • 模拟文件上传(四):对于前面三版中一些出错细节进行处理

    同样,其中涉及到的jar包

    使用前面的文件上传的界面,可以使用这一版

    这里就只贴servlet中的代码了,关于一些解释,全在代码的注释中了:

    package upload;
    
    import java.io.File;
    import java.io.IOException;
    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.FileSizeLimitExceededException;
    import org.apache.commons.fileupload.FileUploadBase.SizeLimitExceededException;
    import org.apache.commons.fileupload.ProgressListener;
    import org.apache.commons.fileupload.disk.DiskFileItemFactory;
    import org.apache.commons.fileupload.servlet.ServletFileUpload;
    import org.apache.commons.io.FileUtils;
    
    import exception.FileTypeErrorException;
    /**
     * 文件上传!细节注意:
     * 		1.限制单文件的大小
     * 		2.限制总文件的大小
     * 		3.限制文件的类型
     * 		4.解决之前的文件同名覆盖的问题
     * 		5.在file下生成有规律有意义,可查找或者安全的目录。
     * 
     * 使用apache的文件上传和下载的组件
     * 1.导入jar包
     * 		commons-fileload-1.2.2.jar
     * 		commons-io-2.1.jar 一个IO流工具(更方便)
     * @author mzy
     *
     */
    public class UpLoadDemo04 extends HttpServlet {
    
    	private static final long serialVersionUID = 987003232758385500L;
    
    	public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    		try {
    			DiskFileItemFactory factory = new DiskFileItemFactory(10*1024, new File("e:/temp"));
    			ServletFileUpload upload = new ServletFileUpload(factory);
    			/*
    			 * 注册一个文件监听器:
    			 * 		监听上传的进度!
    			 */
    			upload.setProgressListener(new MyProgressListener());
    			upload.setHeaderEncoding("utf-8");
    			
    			/*
    			 * 注意限制文件大小的两个方法:
    			 * 		setFileSizeMax(100*1024):单个文件大小不超过100KB
    			 * 		setSizeMax(300*1024):文件总大小不超过300KB
    			 */
    			// 一个request中最大的容量为300KB
    			upload.setSizeMax(300*1024);
    			// 单个文件的最大容量为100KB
    			upload.setFileSizeMax(100*1024);
    			// 解析request
    			List<FileItem> list = upload.parseRequest(request);
    			if(list != null) {
    				for(FileItem item: list) {
    					/*
    					 * 注意:
    					 * 		限制文件的类型。文件的
    					 * 类型(mime-type):image/*
    					 * 只能上传图片
    					 */
    					// 得到文件的类型
    					String contentType = item.getContentType();
    					if(!contentType.contains("image/")) {
    						throw new FileTypeErrorException("文件类型错误,请换一张图片!");
    					}
    					/*
    					 * 使用UUID算法,生成唯一的文件名
    					 * 避免文件覆盖的问题!
    					 */
    					String uuid = UUID.randomUUID().toString();
    					// get到真正的文件名!
    					/*
    					 * 这里我们就不用做兼容性的处理了
    					 * 因我们只用get一个LastIndexOf(".")
    					 * 去获得文件的后缀名,保证文件能够正常的打开!
    					 */
    					String fileName = item.getName();
    					// 获取到后缀名
    					fileName = fileName.substring(fileName.lastIndexOf("."));
    					// 组合新的文件名
    					String newFileName = uuid+fileName;
    					
    					// 得到新的目录结构
    					String dir = "e:/files/"+makeDirectory(newFileName);
    					// 生成目录结构
    					File file = new File(dir);
    					// 如果不存在这个目录结构!
    					if(!file.exists()) { 
    						file.mkdirs(); 
    						// mkdir只能生成单个目录,所以要用mkdirs
    					}
    					//开始文件传输
    					FileUtils.copyInputStreamToFile(item.getInputStream(), new File(dir+newFileName));
    					
    					// 删除item传输的tmp临时文件
    					item.delete();
    				}
    			}
    		} catch (FileTypeErrorException e) {
    			// 捕获文件类型异常
    			request.setAttribute("msg", e.getMessage());
    			request.getRequestDispatcher("/04.upload.jsp").forward(request, response);
    		} catch (FileSizeLimitExceededException e) {
    			// 捕获单个文件大小超规定范围异常
    			request.setAttribute("msg", "单个文件超过设定大小:100KB");
    			request.getRequestDispatcher("/04.upload.jsp").forward(request, response);
    		} catch (SizeLimitExceededException e) {
    			// 捕获总文件大小超规定范围异常
    			request.setAttribute("msg", "总文件超过设定大小:300KB");
    			request.getRequestDispatcher("/04.upload.jsp").forward(request, response);
    		} catch (Exception e) {
    			e.printStackTrace();
    		}
    		
    	}
    	/**
    	 * 思考,生成有意义的目录结构:
    	 * 
    	 * 第一种三层结构: 年-月-日
    	 * 
    	 * 
    	 * 第二种两层结构:通过hashcode生成的更安全的随机目录
    	 * 动态生成新的目录结构:
    	 * 		(第一级目录)/(第二级目录)
    	 * @return 新的目录结构:右边是带斜杠的(左边不带),
    	 * 		       可直接进行字符串拼接
    	 */
    	private String makeDirectory(String fileName) {
    		// 1.得到文件名的hashCode
    		int code = fileName.hashCode();
    		
    		// 2.算出第一层目录的名称
    		// 第一层目录的数字大小不会超过15
    		int first = code & 0xF; // 十六进制的15
    		
    		// 3.算出第二层目录的名称:先右移一位
    		int second = code & (0xF >> 1);
    		return first+"/"+second+"/";
    	}
    	
    	/**
    	 * 实现ProgressListener监听文件上传进度 
    	 */
    	class MyProgressListener implements ProgressListener {
    		/*
    		 * 参数1:目前上传了多少字节
    		 * 参数2:总长度
    		 * 参数3:目前正在第几个文件 
    		 */
    		@Override
    		public void update(long pBytesRead, long pContentLength, int pItems) {
    			System.out.println("正在上传第"+pItems+"个文件!");
    			System.out.println("已经上传了"+pBytesRead+"字节"+",总字节为"+pContentLength+"字节");
    		}
    		
    	}
    	
    	public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    		request.setCharacterEncoding("utf-8");
    		response.setContentType("text/html;charset=utf-8");
    		
    		doGet(request, response);
    	}
    
    }
    


  • 相关阅读:
    疫情环境下的网络学习笔记 python 5.8 数据库入门终章
    疫情环境下的网络学习笔记 python 5.7 navicat数据库,例题,sql注入
    疫情环境下的网络学习笔记 python 5.6 暂时看看
    疫情环境下的网络学习笔记 python 5.5 MYSql 表关系,外键
    疫情环境下的网络学习笔记 python 5.4 数据库基础
    疫情环境下的网络学习笔记 python 4.30 初识数据库
    疫情环境下的网络学习笔记 python 4.29 网络小项目
    XJOI 夏令营501-511测试11 游戏
    XJOI 夏令营501-511测试11 统计方案
    CF1197D Yet Another Subarray Problem
  • 原文地址:https://www.cnblogs.com/mzywucai/p/11053456.html
Copyright © 2011-2022 走看看