博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
java文件的上传和下载(细节问题)
阅读量:3907 次
发布时间:2019-05-23

本文共 8346 字,大约阅读时间需要 27 分钟。

一: 文件的上传: 

要求: 

1:jsp的页面: 
    a: form 表单: 
    b: post 提交: 
    c: form指定一个属性: enctype="multipart/form-data"
    d: file组件: 
2: Servlet: 
  request.getParamter("name");//不生效了: 
  
  ServletInputStream in = request.getInputStream();
  获得数据, 被封装了in 当中, 理论上可以解析数据。  
  
  
  
3: request 请求体当中: 

post请求体: 

请求首行: 
请求头信息: 

请求体: 

-------------------
普通组件: 只有一个头: Content-Dispositon:  name="xxx"

请求体: mrzhang : 填写的内容。 

-------------------
文件上传字段: 两个头: 
Content-Disposition: form-data; name="file"; filename="C:\Users\Mrzhang\Desktop\copy2.txt"
Content-Type: text/plain MIME

文件上传的内容:

xxxx

-----------

二: 解析request当中的请求体: 
 
 1:jar: Apache组织提供的一个公共组件: 
        commons-fileupload 
        commons-io
        
        
    和文件上传相关的两个组件, 这两个组件是强依赖。   
    
    
 2:原理: 
   把request请求体当中的每一个组件的内容都封装到了一个对象当中: 
 FileItem对象: 使用对象的方法和属性来获得数据。 
 
 3:获得FileItem: 
 a: 获得工厂: 
 b: 获得解析器: 
 c: 使用解析器解析request,得到fileItme 对象: 
 
 对象的代码: 
 // 获得工厂: 
 DiskFileItemFactory Factory = new DiskFileItemFactory(); 
 //获得解析器: 
 ServletFileUpload  upload = new ServletFileUpload(Factory); 
 
 // 解析request,获得所有的FileItem对象: 
 List<FileItem>  list=  upload.parseRequest(request);

 4: FileItem 类的详解: 
 
  isFormField() 判断组件是一个普通组件还是一个文件上传组件: true,普通组件:false: 文件上传组件: 
  getFieldName() 返回普通字段属性的值。  name= username  获得是username的值: 
  getString();  获得普通字段上传的内容。 
  
  文件上传组件: 
  getName();获得文件的名称: 
  getSize();会的文件上传的字节大小。 long 
  getInputStream();获得文件上传对应的流: 
  write(File file) ; 文件的内容写到指定的位置:  
 

 

三: 文件上传的具体代码;  

  
  (1)引入jar包: 
  (2)准备页面: 
  (3)准备Servlet:  
 
四: 细节: 
1:上传的普通字段的内容: 乱码: getString("utf-8"); 
2:上传的文件不能被外界直接访问, 应该隐藏起来: 目的,安全; 
   应该吧文件上传到web-inf下,内容不能被外界直接访问。

  获得为web-inf/files的位置: 在tomcat上真实的位置: 

  ServletContext.getRealPath("/WEB-INF/files");
  
3: 文件的的文件的路径问题:  
   不同的浏览器上传的路径不一致。 有的浏览器上传的上传相对路径, 有的浏览器上传的是绝对路径。 大部分浏览器上传的相对路径。 
   a.txt
   c:\user\mrzhang\files\a.txt
   
   截取出文件的名称: 
  String filename =  f2.getName();
  
  //截取: 
  int index = filename.lastIndexOf("\\");
  if(index!=-1){
    filename = filename.subString(index+1);
  }
 
4: 上传文件的名称乱码问题: 
  request.setCharacterEncoding("utf-8");
  解析器当中提供了一个方法: 
  servletFileUpload.setHeaderEncoding("utf-8");// 解析器提供。优先级高:  对 request.setCharacterEncoding("utf-8");的封装
5: 文件同名的问题: 
  解决方式一:   uuid+"filename".后缀名称; 
  解决方式二:    new Date().getTime()+"filename"; 
6: 上传的文件不能存在同一个目录下 :  上传的目录打散: 
  a: 时间打散:   获得当前的时间, 创造目录:  
  b: 文件名称首字母打散:  abc.txt :  charAt("0")
  c: 哈希打散:  
  实现步骤: 
         (1)  获得文件名称: 
         (2)获得哈希值: hashCode(); int
         (3)转换成十六进制: Integer.toHexString(); //字符串: 9A8B7C
         (4)  获得字符串的前两个:  第一个字母做第一层目录。     第二个字母做第二层目录。  16*16
   
 

package com.yidongxueyuan.web.servlet;import java.io.File;import java.io.IOException;import java.util.List;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.FileUploadException;import org.apache.commons.fileupload.disk.DiskFileItemFactory;import org.apache.commons.fileupload.servlet.ServletFileUpload;/* * 处理文件上传的servlet:  *  * 1:细节:  *  乱码解决了文件名称上传的乱码,  *  普通字段: getString("utf-8"); *   * 2:对相对路径进行了处理:  subString();  *  * 3: 文件名称同名的问题,处理:  *  * 4: 哈希打散:  *   filename.hashCode(); *   filename.toHexString();  *   filename.charAt(0);   *    *  File dir=   new File(root, charAt(0)+"\"+charAt(1)); *   *  File destFile = new File(dir, savefilename); *   *  write();  *    *   *   *   */public class FileUploadServlet extends HttpServlet {	public void doPost(HttpServletRequest request, HttpServletResponse response)			throws ServletException, IOException {		//解决上传文件名称的乱码问题:  		request.setCharacterEncoding("utf-8");		response.setContentType("text/html;charset=utf-8");//告知客户端浏览器响应的内容: text/html charset=utf-8		/*		 * 三步走: 		 * 1:获得工厂: 		 * 2: 获得解析器: 		 * 3:解析request:		 */				//获得获得解析器工厂; 		DiskFileItemFactory factory = new DiskFileItemFactory(1024*20,new File("C:/Users/Mrzhang/javaEE/javaEE-07/temp")); //		DiskFileItemFactory factory = new DiskFileItemFactory(); 		//获得解析器:		ServletFileUpload upload = new ServletFileUpload(factory);				//解析之前设置上传单个文件的大小: //		upload.setFileSizeMax(1024*10);//这是最大是10K: //		upload.setSizeMax(1024*1024*10); //设置了整个request 的大小, 如果上传的request 大于设定的最大值, 也会触发异常				//解析request: 获List
try { List
fileItem = upload.parseRequest(request); //解析fileItem当中的内容: web-inf下的: 目录安全: 不能被外界随机的访问: FileItem f2 = fileItem.get(1);//文件上传的组件: /* * 获得文件的名称: * f2.getName(); * f2.getInputStream(); 文件当中的内容: * new FileOutputStream("path"); * 实现流对接: */ /* * 获得要保存的路径: * WEB-INF/files/ * 目的: 安全: 不能被外界直接通过浏览器访问: * 获得ServletContext对象: 获得真实路径: */ String root = this.getServletContext().getRealPath("/WEB-INF/files/"); //获得上传文件的名称: String filename = f2.getName(); /* * 细节的处理: * 1: 绝对路径的问题: 兼顾小部分浏览器: */ int index = filename.lastIndexOf("\\"); if(index != -1){//说明路径当中存在\\ : filename = filename.substring(index+1); } /* * 处理文件同名的问题: uuid */ String savename = CommonsUtils.uuid()+"_"+filename; /* * 哈希码 生产多个目录: 将上传的文件存放在多个目录当中: */ // 1:获得文件名称的哈希值: int code = filename.hashCode();// int // 2:获得code 的十六进制的值: String hex = Integer.toHexString(code);// 9c0a1d // 获得前两位: 充当第一层目录 和第二层目录: char firstDir = hex.charAt(0); char secDir = hex.charAt(1); /* * 获得保存的文件路径: */ File dirFile = new File(root, firstDir+"/"+secDir);//存放的目录: //dirFile 如果不存在,创建: if(!dirFile.exists()){//说明不存在 //创建“: dirFile.mkdirs();//创建多层的目录: } //创建保存的文件: File destFile = new File(dirFile, savename); //保存: try { f2.write(destFile); } catch (Exception e) { e.printStackTrace(); } } catch (FileUploadException e) { // 触发异常: 说明文件过大: request.setAttribute("msg", "您传的文件过大"); request.getRequestDispatcher("/index.jsp").forward(request, response); e.printStackTrace(); } }}

 
文件的下载

 

文件的下载:  

  原来: 服务器响应回来的数据:text/html 浏览器能够自动解析:   
 
 原理: 现在要求服务器传递过来的数据是一个字节数组: 只需要在服务器端响应回来一个字节流即可。 
 
 下载的要满足的条件一个流两个头: 
 
  流: 服务器端响应回来的字节流.  new FileOutputStream("String path");
  设置两个头: 
  * Content-Type: 这是成文件类型的MIME类型: text/css text/javascript : tomcat : web.xml 
  * Content-Disposition :  默认值: inline 在浏览器当中打开。  
        文件下载: attachment;filename=xxxx; 
  
 下载的细节: 
 1: 下载文件的名称乱码问题:  
   通用的解决方案: 
 new String(name.getBytes("gbk"),"iso-8859-1");
 弊端: 该种方式能够解决大部分浏览器,  但是个别的特殊字符不能解决: 
 
 不同的浏览器对文件的名称编码方式不一样: 
  fixfox: Base64 : 
  其他的浏览器: url
  
 2:  通用性方式: 提供一个工具类到时候再搜吧 : 

文件下载 servlet代码如下:

package com.yidongxueyuan.web.servlet;import java.io.FileInputStream;import java.io.IOException;import java.net.URLEncoder;import javax.servlet.ServletException;import javax.servlet.ServletOutputStream;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import org.apache.commons.io.IOUtils;import sun.misc.BASE64Encoder;/* * 负责下载的Servlet:  */public class DownLoadFileServlet extends HttpServlet {	public void doGet(HttpServletRequest request, HttpServletResponse response)			throws ServletException, IOException {	/*	request.setCharacterEncoding("utf-8");		response.setContentType("text/html;charset=utf-8");*/						/*		 *  1: 文件的下载具备一个流: 两个头: 		 */				String filename = "C:/Users/Mrzhang/Desktop/API/a练习图片/girl.jpg"; 				//头信息:  		// Content-Type: MIME 文件的MIME类型: 		String conentType= this.getServletContext().getMimeType(filename);//能够获得.jpg文件的MIME类型: image/jpeg 				String name = "凤姐.jpg"; //		String savename =  new String(name.getBytes("gbk"),"iso-8859-1"); 解决 大部分情况: 				String savename = FilenameEncodingUtils.filenameEncoding(name, request);		String contentDisposition = "attachment;filename="+savename;				//设置响应头信息: 		response.setHeader("Content-Type",conentType ); 		response.setHeader("Content-Disposition", contentDisposition); 						//准备的一个流: 				//将图片读取到fis当中: 		FileInputStream fis = new FileInputStream(filename);		//响应输出流: 		ServletOutputStream out = response.getOutputStream(); 		//流对接: IOUtils 		IOUtils.copy(fis, out);				fis.close(); 		out.close(); 					}} class FilenameEncodingUtils {	// 用来对下载的文件名称进行编码的!	public static String filenameEncoding(String filename, HttpServletRequest request) throws IOException {		String agent = request.getHeader("User-Agent"); //获取浏览器		if (agent.contains("Firefox")) {			BASE64Encoder base64Encoder = new BASE64Encoder();			filename = "=?utf-8?B?"					+ base64Encoder.encode(filename.getBytes("utf-8"))					+ "?=";		} else if(agent.contains("MSIE")) {			filename = URLEncoder.encode(filename, "utf-8");		} else {			filename = URLEncoder.encode(filename, "utf-8");		}		return filename;	}}

 

 

转载地址:http://lwqen.baihongyu.com/

你可能感兴趣的文章
468. 验证IP地址
查看>>
486. 预测赢家
查看>>
494. 目标和
查看>>
520. 检测大写字母
查看>>
数据处理和训练模型的技巧
查看>>
vb 中如何做同步 异步?
查看>>
geturl
查看>>
2016年安大校赛(补题)
查看>>
BESTCODER ROUND92 1001.Skip the Class
查看>>
POJ 1661 Help Jimmy
查看>>
百练OJ 2755 神奇的口袋(递归+递推)
查看>>
HDU 1003 Max Sum
查看>>
Code Vs 1014 装箱
查看>>
循环队列,队链的实现
查看>>
HDU 2602 Bone Collector (01背包)
查看>>
POJ 1837 Blance (01背包)
查看>>
HDU 2456 饭卡 (01背包)
查看>>
HDU 1559 最大子矩阵
查看>>
Open Judge 4010 :2011
查看>>
百练OJ-2815 城堡问题【DFS】
查看>>