zoukankan      html  css  js  c++  java
  • 模拟文件上传(五):为文件添加描述信息

    同样,其中涉及到的jar包

    在这里我为文件上传的时候,添加了描述,希望文件上传的时候,也附带一些文字信息;

    但是我在servlet中request.getParameter("info1");
    info的内容为空:null;


    回忆到为了上传文件,我把表单的格式(entype)修改成了:
      enctype="multipart/form-data"
      这种情况下的内容必须通过POST方式这是第一点;
      其次内容的格式是:
      ------------------121211212
      Content-Disposition: form-data; name="attachment01"; filename="aaa.txt"
      Content-Type: text/plain
     
      hello world 
      ------------------121211212
      Content-Disposition: form-data; name="attachment02"; filename="bbb.txt"
      Content-Type: text/plain 
      
      xxxx
      dfhuhfhdsu
      ------------------121211212--
      
      
      之前默认的是:
      enctype="application/x-www-form-urlencoded"
      可以通过POST传值,和GET的URL传值(http://dssss?name=mzy&&password=123456):
      其中的格式解析了都是:
      attachement01=aaa.txt&&attachement02=bbb.txt
      
      
      格式都不同了,所以不能再使用简单的,request.getParameter了!
      
      在开发模式下查看此刻的info的格式为:




    我发现其实普通的表单字段也是封装在List<FileItem>中的
    每一个input,不管是文件还是普通字段,都是一个item对象。
    所以可以通过组件中的ifFormField方法进行是否是简单窗体字段的判断(是否是文件)
    然后通过其中的getString方法,去得到其中的内容;
    getString方法可以传参,传编码格式:

    具体如:getString("utf-8");

    没设置getString的编码的时候:

    设置utf-8之后:

    下面贴代码了:

    JSP中:

    <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
    <html>
      <head>
        <title>文件上传</title>
      </head>
      <body>
    	  <font color="red">${msg }</font>
    	   <form action="${pageContext.servletContext.contextPath }/servlet/UpLoadDemo05" method="POST" enctype="multipart/form-data">
    	   		请选择要上传的文件一:<input type="file" name="attachment01" />描述一:<input type="text" name="info1"/><br/>
    	   		请选择要上传的文件二:<input type="file" name="attachment02" />描述二:<input type="text" name="info2"/><br/>
    	   		<!-- 请选择要上传的文件三:<input type="file" name="attachment03" /><br/> -->
    	   		<input type="submit" value="上传文件"/>
    	   </form>
      </body>
    </html>
    

    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下生成有规律有意义,可查找或者安全的目录。
     * 
     * 		6.增加描述!!!
     * 
     * 使用apache的文件上传和下载的组件
     * 1.导入jar包
     * 		commons-fileload-1.2.2.jar
     * 		commons-io-2.1.jar 一个IO流工具(更方便)
     * @author mzy
     */
    public class UpLoadDemo05 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) {
    				
    				// String info1 = request.getParameter("info1");
    				// System.out.println("info1"+info1);
    				for(FileItem item: list) {
    					/*
    					 * 确定文件项实例是否表示简单窗体字段。
    					 * 		如果实例表示简单表单字段,则返回true;
    					 * 		如果它表示已上传文件,则为false。
    					 */
    					if(item.isFormField()) { 
    						// 除文件外的其它表单组件
    						if(item.getFieldName().equals("info1")) {
    							String info1 = item.getString("utf-8");
    							System.out.println("info1 = "+info1);
    						}
    						if(item.getFieldName().equals("info2")) {
    							String info2 = item.getString("utf-8");
    							System.out.println("info2 = "+info2);
    						}
    					} else {
    						/*
    						 * 注意:
    						 * 		限制文件的类型。文件的
    						 * 类型(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);
    	}
    
    }
    


  • 相关阅读:
    safenet 超级狗 java调用 小计
    解析Javascript中大括号“{}”的多义性
    openlayers研究(一) 初始化流程
    计算球面两点间距离实现Vincenty+Haversine
    搭建高可用mongodb集群(四)—— 分片
    搭建高可用mongodb集群(三)—— 深入副本集内部机制
    搭建高可用mongodb集群(二)—— 副本集
    C# 7.1 的 Async Main()
    深入理解 C# 7.1 提供的 async 非同步 Main() 方法
    使用Blazor Server 线路处理程序 (circuit handler)跟踪打开的SignalR连接
  • 原文地址:https://www.cnblogs.com/mzywucai/p/11053455.html
Copyright © 2011-2022 走看看