本文共 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*16package 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: 获Listtry { 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/