JavaWeb—文件上传和下载

最近在学习Web的文件上传和下载对于文件上传,浏览器在上传的过程中是将文件以流的形式提交到服务器端的,如果直接使用Servlet获取上传文件的输入流然后再解析里面的请求参数是比较麻烦,所以一般选择采用apache的开源工具common-fileupload这个文件上传组件。这个common-fileupload上传组件的jar包可以去apache官网上面下载,也可以在struts的lib文件夹下面找到,struts上传的功能就是基于这个实现的。common-fileupload是依赖于common-io这个包的,所以还需要下载这个包。

项目结构:

JavaWeb—文件上传和下载

创建一个UploadHandleServlet继承HttpServlet 并重写doGet 和doPost方法

public class UploadHandleServlet extends HttpServlet {
	 @Override
	 public void doGet(HttpServletRequest request, HttpServletResponse response)
	     throws ServletException, IOException {
		 
		 System.out.println("进入文件上传");
		 //得到上传文件的保存目录,将上传的文件存放于WEB-INF目录下
		 String savepath = this.getServletContext().getRealPath("/WEB-INF/upload");
		 System.out.println(savepath);
		 //		 String savepath ="E:/lijilin";
		 //上传时生成临时文件保存目录
		 String tempaht=this.getServletContext().getRealPath("/WEB-INF/temp");
		 
		 File tempfile=new File(tempaht);
		 //判断文件目录是否存在
		 if (!tempfile.exists()) {
			
			 tempfile.mkdir();//创建临时表
		}
		 //消息提示
		 String messge="";
		 //使用Apach文件上传组件处理
		 try {
			
		
		 //1创建一个DiskFileItemFactory工厂
		 DiskFileItemFactory factory=new DiskFileItemFactory();
		 //设置工厂缓存区的大小,当上传文件大小超过缓存区大小的时候就会生成一个临时文件存放到指定临时目录中
		 factory.setSizeThreshold(1024*100);//设置缓存区的大小为100KB,如果不指定默认10KB
		 //设置临时生成文件保存目录
		 factory.setRepository(tempfile);
	
		 //2创建文件上传解析器
		 ServletFileUpload upload=new ServletFileUpload(factory);
		 //监听文件上传进度
		 upload.setProgressListener(new ProgressListener() {
			
			@Override
			public void update(long pBytesRead, long pContentLength, int arg2) {
				// TODO Auto-generated method stub
				System.out.println("文件大小:"+pContentLength+"当前已处理:"+pBytesRead);
			}
		});
		 //3处理乱码
		 upload.setHeaderEncoding("UTF-8");
		 //4判断提交的数据是否是表单数据
		 if (!ServletFileUpload.isMultipartContent(request)) {
			//按照传统方式获取数据
			 return;
		}
		 //设置上传文件大小的最大值
		 upload.setFileSizeMax(1024*1024);
		 //设置上传文件总量的最大值,最大值=同时上传多个文件值的综合
		 upload.setSizeMax(1024*1024*10);//10MB
		 //5.使用servletFileUpload解析器上传数据
		 List<FileItem> list=upload.parseRequest(request);
		 for (FileItem item : list) {
			//如果fileitem中封装是普通项输入数据
			 if (item.isFormField()) {
				String name = item.getFieldName();
				//解决普通传输项中文乱码问题
				String value = item.getString("UTF-8");
				System.out.println(name+"="+value);
			}else {
				//如果fileitem中封装的是上传文件
				//得到上传文件的名称
				String filename = item.getName();
				System.out.println(filename+"文件名称");
				if (filename==null||filename.trim().equals("")) {
					continue;
				}
				filename=filename.substring(filename.lastIndexOf("\\")+1);
				//得到上传文件的扩展名
				String fileExtName=filename.substring(filename.lastIndexOf(".")+1);
				System.out.println("上传文件的扩展名"+fileExtName);
				//获取Item中文件的输入流
				InputStream in = item.getInputStream();
				//得到文件保存的名称
				String saveFilename=makeFileName(filename);
				//得到文件保存目录
				String realSavepath=makePath(saveFilename, savepath);
				
				//创建一个输出流
				FileOutputStream out=new FileOutputStream(realSavepath+"\\"+saveFilename);
				//创建一个缓冲区
				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();
				messge="文件上传成功!";
				
			}
		}
		 } catch (Exception e) {
				messge="文件上传失败";
				e.printStackTrace();
		}
		 request.setAttribute("message", messge);
		 request.getRequestDispatcher("/page/message.jsp").forward(request,response );
		 
	 }
	 @Override
	 public void doPost(HttpServletRequest request, HttpServletResponse response)
	             throws ServletException, IOException {
	 
	         doGet(request, response);
     }
	 
	 
	 /**
	    * @Method: makeFileName
	     * @Description: 生成上传文件的文件名,文件名以:uuid+"_"+文件的原始名称
	     * @Anthor:孤傲苍狼
	    * @param filename 文件的原始名称
	     * @return uuid+"_"+文件的原始名称
	     */ 
	     private String makeFileName(String filename){  //2.jpg
	         //为防止文件覆盖的现象发生,要为上传文件产生一个唯一的文件名
	        return UUID.randomUUID().toString() + "_" + filename;
	     }
	     
	     /**
	      * 为防止一个目录下面出现太多文件,要使用hash算法打散存储
	      * @Method: makePath
	      * @Description: 
	      * @Anthor:孤傲苍狼
	      *
	      * @param filename 文件名,要根据文件名生成存储目录
	      * @param savePath 文件存储路径
	      * @return 新的存储目录
	      */ 
	      private String makePath(String filename,String savePath){
	          //得到文件名的hashCode的值,得到的就是filename这个字符串对象在内存中的地址
	          int hashcode = filename.hashCode();
	          int dir1 = hashcode&0xf;  //0--15
	         int dir2 = (hashcode&0xf0)>>4;  //0-15
	         //构造新的保存目录
	          String dir = savePath + "\\" + dir1 + "\\" + dir2;  //upload\2\3  upload\3\5
	         //File既可以代表文件也可以代表目录
	         File file = new File(dir);
	          //如果目录不存在
	          if(!file.exists()){
	              //创建目录
	              file.mkdirs();
	          }
	          return dir;
	      }
}

创建一个uplod.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>文件上传</title>
</head>
<body>
	<form action="${pageContext.request.contextPath}/servlet/UploadHandleServlet" enctype="multipart/form-data" method="post">
       上传用户:<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>
</body>
</html>

创建一个message.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>消息提示</title>
</head>
<body>
	${message}
</body>
</html>

参考资料:https://www.cnblogs.com/xdp-gacl/p/4200090.html