**文件上传的概述** 1.了解什么是文件上传 2.文件上传需要大家记住编写客户端需要有3个注意事项。 3.什么是文件上传 * 把本地的文件保存到服务器端 4.做文件上传,该怎么做? * 客户端 * 选择一个要上传的文件 * 需要提供文件的选择输入框(<input type="file">) * 注意:如果完成文件的上传,必须有3点注意事项的 * 编写表单,method="post" 必须是post * 表单中还有一个属性,enctype="multipart/form-data" * 编写文件的选项框 <input type="file" name="必须要指定,名称可以任意"> * 服务器端 * 把上传的文件写入到某个指定的文件夹下 ![](./图片/01-文件上传的概述.bmp) ---------- **Fileupload文件上传的组件** 1.由apache提供的开源的jar包 * 导入开发的jar包 * commons-fileupload-1.2.1.jar * commons-io-1.4.jar 2.入门的开发 * 开发的步骤,开发的步骤比较固定 ![](./图片/02-FileUpload开发的流程.bmp) ---------- **文件上传入门案例** 1.编写入门的案例,目的:让大家来熟悉开发的步骤,使用一些对象和方法,后面讲解。 2.文件上传的案例步骤 * 客户端 * 注意3个注意事项 * 服务器端 * 采用的是FileUpload文件上传的组件,不要忘记导入开发的jar包。 * 创建工厂类,生成对象 * 创建核心解析类,解析request请求,获取到文件项(FileItem) * 操作FileItem类的方法就可以完成文件的上传了 ---------- ### FileUpload组件的类和方法 ### ---------- **DiskFileItemFactory类** 1.DiskFileItemFactory:代表磁盘文件项工厂类,作用:用来生产FileItem对象的。 2.方法 * DiskFileItemFactory() -- 空的构造经常使用的。 * DiskFileItemFactory(int sizeThreshold, java.io.File repository) * sizeThreshold -- 设置上传文件的缓冲区的大小,如果不指定,有默认值是10K * repository -- 设置临时文件的存储目录,如果上传的文件,超过了缓冲区的大小,产生临时文件,设置临时文件存储的目录。 * void setSizeThreshold(int sizeThreshold) -- 设置缓冲区的大小 * void setRepository(java.io.File repository) -- 设置临时文件的存储目录(上传的文件超过了缓冲区的大小,产生临时文件) 3.总结 * 上述的这两个方法,如果不设置都有默认值的。 ---------- **ServletFileUpload类(解析request)** 1.ServletFileUplod 代表的文件上传的类,作用:用来解析request请求。 2.方法 * ServletFileUpload(FileItemFactory fileItemFactory) * static boolean isMultipartContent(javax.servlet.http.HttpServletRequest request) -- 判断表单的enctype值设置的是否正确 * java.util.List parseRequest(javax.servlet.http.HttpServletRequest request) -- 解析request请求,返回的是List集合 * void setHeaderEncoding(java.lang.String encoding) -- 解决中文文件名称乱码的问题。 * void setFileSizeMax(long fileSizeMax) -- 设置单个上传文件的大小 * void setSizeMax(long sizeMax) -- 设置总大小 3.总结(掌握) * parseRequest(request) -- 解析request请求 * setHeaderEncoding() -- 解决中文乱码问题呢 * setSizeMax() -- 设置上传文件的总大小 * void setFileSizeMax() ---------- **FileItem接口(文件项)** 1.FileItem类:代表文件项(普通表单项(文本框、密码、单选),又有可能文件的上传项) 2.方法 * boolean isFormField() * 判断当前的fileItem对象是否是普通表单项还是文件上传项?如果返回true,说明是普通表单项,如果是false,是文件上传项 * 如果是普通表单项(文本框 密码框 复选框 单选框 下拉列表) * java.lang.String getFieldName() -- 获取的表单中的name属性的值(例如:filedesc) * java.lang.String getString() -- 获取到用户输入的值(没有解决乱码的问题) * java.lang.String getString(String encoding) -- 获取到用户输入的值(解决中文乱码问题) * 如果是文件上传项 * java.lang.String getName() -- 获取的上传文件的名称(ServletFileUpload类中setHeaderEncoding()解决中文乱码) * java.io.InputStream getInputStream() -- 获取到上传文件的输入流 * void write(java.io.File file) -- 直接写入文件 * void delete() -- 删除临时文件的(注意:删除的代码需要放在流关闭之后) 3.总结 * 上述所有 ---------- **文件上传存在的问题** 1.第一个问题:如果使用的是IE6浏览器,存在问题。 * 如果是IE6的浏览器,获取的文件的名称是:C:\class\resource\hello.txt * 如果浏览器是IE的一些版本(IE6肯定存在该问题),如果使用的是IE6版本的浏览器,选择文件的时候,选择完文件,点击上传。 * 在Servlet中获取到的文件名称是包含文件的路径的。 2.第二个问题:request.getParameter()方法已经不能获取到表单的内容了。(重要的) * 使用request对象的时候,request.getParameter()方法,在文件上传中,使用的enctype="multipart/form-data"方式,那么request.getParameter()获取不到值了。 3,注意; request.getParameter()已经不能获取到值了!!!
upload.jsp:
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Insert title here</title> </head> <body> <h3>文件的上传</h3> <form action="${pageContext.request.contextPath }/upload" method="post" enctype="multipart/form-data"> 文件描述:<input type="text" name="filedesc"/><br/> 文件上传:<input type="file" name="upload"/><br/> <input type="submit" value="上传"/> </form> </body> </html>
UploadServlet:
public class UploadServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { /** * 1.创建一个工厂类 * 2.创建能解析request对象的类 * 3.解析request请求 * 4.返回的是List集合 * 5.遍历集合,获取到每一个FileItem * 6.操作FileItem中方法完成文件的上传 */ //判断,表单的enctype属性值是否设置正确,返回true,说明设置正确。返回false,不正确 if(!ServletFileUpload.isMultipartContent(request)){ //说明设置不正确 throw new RuntimeException("亲,您没有设置正确的enctype属性的值"); } //1.创建工厂类 DiskFileItemFactory factory=new DiskFileItemFactory(); //设置缓冲区的大小 设置2M factory.setSizeThreshold(2*1024*1024); //设置临时文件的存储目录 String tempPath=this.getServletContext().getRealPath("/temp"); System.out.println(tempPath); //创建文件目录 File tempFile=new File(tempPath); factory.setRepository(tempFile); //2.创建能解析request对象的类 ServletFileUpload upload=new ServletFileUpload(factory); //设置头的编码,解决中文文件名称乱码的问题 upload.setHeaderEncoding("utf-8"); //设置文件上传的总大小 4M upload.setSizeMax(4*1024*1024); try { //3.解析request请求 //4.返回的是List集合 List<FileItem> list=upload.parseRequest(request); //5.遍历集合,获取到每一个FileItem for (FileItem fileItem : list) { //需要判断,当前的fileItem是否是文件描述还是文件上传 //isFormField(),返回true,说明表单的字段(text,password,checkbox,radio) if(fileItem.isFormField()){ //获取表单中name属性的值 String name=fileItem.getFieldName(); //文件描述,获取用户输入的值 String value= fileItem.getString(); String value_=fileItem.getString("UTF-8"); System.out.println(name+":::"+value+value_); }else{ //返回false,说明type="file" 说明是文件上传,需要获取用户上传的文件的文件名称 String fileName=fileItem.getName(); //生成唯一的文件的名称 String uuid=UUID.randomUUID().toString(); //名称完全换掉hello.txt --> ffggerwefd.txt int i=fileName.lastIndexOf("."); //文件的后缀名 String lastName=fileName.substring(i); String uuidName=uuid+"_"+lastName; //获取到的是文件的输入流 InputStream in=fileItem.getInputStream(); //获取upload文件夹的绝对路径 String path=this.getServletContext().getRealPath("/upload"); System.out.println("upload文件夹的绝对路径:"+path); //创建输出流 OutputStream out=new FileOutputStream(path+"/"+uuidName); byte[] by=new byte[1024]; int len=0; while((len=in.read(by))!=-1){ out.write(by, 0 ,len); } out.close(); in.close(); } } } catch (FileUploadException e) { e.printStackTrace(); } } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
**多文件上传(js控制多个上传输入项)** 1.多文件上传 * 需求:点击添加按钮,生成多个文件的上传项。点击删除的按钮,删除该个上传项。点击上传按钮,把选择的所有的文件上传到服务器端。 * 前台和后台
moreupload.jsp:
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Insert title here</title> <script type="text/javascript" src="${pageContext.request.contextPath }/js/jquery-1.8.3.js"></script> <script type="text/javascript"> $(function(){ $("input[type=‘button‘]").click(function(){ //创建div var $div=$("<div></div>"); //创建选择框 var $input=$("<input type=‘file‘ name=‘upload‘/>"); var $del=$("<input type=‘button‘ value=‘删除‘/><br/>"); //给删除按钮绑定事件 $del.click(function(){ //删除一行,小div $(this).parent().remove(); }); $div.append($input); $div.append($del); //生成的小div存入大的div $("#divId").append($div); }); }); </script> </head> <body> <h3>多文件的上传</h3> <form action="${pageContext.request.contextPath }/upload" method="post" enctype="multipart/form-data"> <input type="button" value="添加" /> <input type="submit" value="上传"/> <!-- div,存放生成文件的选择项 --> <div id="divId"></div> </form> </body> </html>
案例:上传图书封面
AddServlet:
/** * 添加商品(包含文件的上传) * @author mjl * */ public class AddProduct extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { DiskFileItemFactory factory=new DiskFileItemFactory(); ServletFileUpload upload=new ServletFileUpload(factory); //解决中文文件名称乱码问题 upload.setHeaderEncoding("utf-8"); //创建一个Map,存入用户输入的值 Map<String,String> map=new HashMap(); Product product=new Product(); String uuidName=null; try { List<FileItem> list = upload.parseRequest(request); for (FileItem fileItem : list) { if(fileItem.isFormField()){ //获取到每个表单项的name的值 String name=fileItem.getFieldName(); //获取到用户输入的值 String value=fileItem.getString("utf-8"); //存入到map集合 map: pname 故事会 price 10 map.put(name, value); }else{ String fileName=fileItem.getName(); if(fileName!=null && !fileName.trim().isEmpty()){ String uuid=MyUUIDUtils.getUUID(); int i=fileName.lastIndexOf("."); String lastName=fileName.substring(i); //唯一的文件名称 uuidName=uuid+lastName; InputStream in=fileItem.getInputStream(); String path=this.getServletContext().getRealPath("/bookcover"); System.out.println(path); OutputStream out=new FileOutputStream(path+"/"+uuidName); int len=0; byte[] by=new byte[1024]; while((len=in.read(by))!=-1){ out.write(by, 0, len); } out.close(); in.close(); fileItem.delete(); } } } //使用BeanUtils来封装数据 BeanUtils.populate(product, map); product.setImgUrl(uuidName); ProductService ps=new ProductService(); ps.save(product); //如果添加成功了,跳转查询所有商品的方法 response.sendRedirect(request.getContextPath()+"/product?method=findAll"); } catch (Exception e) { e.printStackTrace(); } } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
文件下载:
download.jsp:
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Insert title here</title> </head> <body> <h3>文件下载的页面</h3> <h4><a href="${pageContext.request.contextPath }/download?filename=大二.jpg">大二.jpg</a></h4> <h4><a href="${pageContext.request.contextPath }/download?filename=guoguo.jpg">guoguo.jpg</a></h4> <h4><a href="${pageContext.request.contextPath }/download?filename=wangwang.txt">wangwang.txt</a></h4> </body> </html>
DownloadServlet:
/** * 文件的下载 * @author mjl * */ public class DownloadServlet extends HttpServlet { protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //先获取文件的名称 String filename=request.getParameter("filename"); //两个头(响应头),一个流(文件的输入流) //content-Type 代表要下载文件的MIME的类型 txt=text/plain jpg=image/jpeg //response.senContentType("text/html;charset=utf-8"); String mimeType=getServletContext().getMimeType(filename); System.out.println("文件的MIME类型:"+mimeType); response.setContentType(mimeType); //弹出下载的窗口 Content-Disposition 值 attachment;filenmae=加上文件名称 response.setHeader("Content-Disposition", "attachment;filename="+filename); //获取download的路径 String path=this.getServletContext().getRealPath("/download"); InputStream in=new FileInputStream(path+"/"+filename); //使用response对象,响应 OutputStream out=response.getOutputStream(); byte[] by=new byte[1024]; int len=0; while((len=in.read(by))!=-1){ out.write(by,0,len); } } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { } }