JAVA文件上传 ServletFileUpLoad 实例
1. jsp
1 <%@ page language="java" contentType="text/html" pageEncoding="utf-8"%> 2 <!DOCTYPE html> 3 <html> 4 <head> 5 <title>文件上传</title> 6 </head> 7 <body> 8 <form action="FileUploadServlet" method="post" enctype="multipart/form-data"> 9 用户名:<input type="text" name="name"><br> 10 文件1:<input type="file" name="f1"><br> 11 文件2:<input type="file" name="f2"><br> 12 <input type="submit" value="提交"> 13 </form> 14 15 </body> 16 </html>
2. java
文件上传的前提 1.form表单的method必须是post 2.form表单的enctype必须是multipart/form-data 以二进制字节流 进行提交 传统接收参数的方式无效 DiskFileItemFactory:环境 void setSizeThreshold(int sizeThreshold) 设置缓冲区大小,默认10KB 超出将使用临时文件上传 void setRepository(File repository) 设置临时文件路径 ServletFileUpload:核心操作类 public void setSizeMax(long sizeMax)设置总文件的大小 public void setFileSizeMax(long fileSizeMax):设置单个文件的大小 public List parseRequest(javax.servlet.http.HttpServletRequest req) 解析请求正文内容 public static boolean isMultipartContent(HttpServletRequest req)//判断enctype FileItem:输入域 boolean isFormField():判断是否是普通字段 String getName():获取上传文件名 String getFieldName():获取普通字段的字段名 String getString():获取普通字段的值 String getContentType() 获得文件类型 InputStream getInputStream()以流的形式返回上传文件的主体内容 void delete()删除临时文件 文件上传中需要注意的问题 1.保证安全 上传文件放在WEB-INF目录中 2.中文乱码问题 普通字段乱码 String fieldValue = item.getString("GBK"); 文件名乱码 request.setCharacterEncoding("GBK"); 3.重名文件覆盖 1.UUID 2.使用文件上传日期分类存储 3.System.currentMillions() 4.限制文件上传类型 1.endsWith("")这种方式不可取 2.判断其mime类型 getContentType() 5.限制用户上传文件的大小 1.限制单个上传文件的大小 upload.setFileSizeMax(4*1024*1024); 2.限制总文件大小 upload.setSizeMax() 6.临时文件 item.delete(); 7.多个文件上传时,没有上传内容的问题 if(fileName==null||"".equals(fileName.trim())){ continue; } 8.上传进度检测 upload.setProgressListener(new ProgressListener(){ 参数一:已上传的字节数 参数二:总字节数 参数三:第几项 @Override public void update(long arg0, long arg1, int arg2) { // TODO Auto-generated method stub System.out.println(arg0+" "+arg1+" "+arg2); } });
1 package cn.gs.ly; 2 3 import java.io.File; 4 import java.io.FileOutputStream; 5 import java.io.IOException; 6 import java.io.InputStream; 7 import java.io.OutputStream; 8 import java.util.List; 9 10 import javax.servlet.ServletException; 11 import javax.servlet.http.HttpServlet; 12 import javax.servlet.http.HttpServletRequest; 13 import javax.servlet.http.HttpServletResponse; 14 15 import org.apache.commons.fileupload.FileItem; 16 import org.apache.commons.fileupload.FileUploadException; 17 import org.apache.commons.fileupload.ProgressListener; 18 import org.apache.commons.fileupload.disk.DiskFileItemFactory; 19 import org.apache.commons.fileupload.servlet.ServletFileUpload; 20 21 22 public class FileUploadServlet extends HttpServlet { 23 @Override 24 protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 25 try { 26 //得到上传文件的保存目录。 将上传的文件存放于WEB-INF目录下,不允许外界直接访问,保证上传文件的安全 27 String realPath = this.getServletContext().getRealPath("/upload");// /WEB-INF/files 28 System.out.println("文件存放位置:"+realPath); 29 //设置临时目录。 上传文件大于缓冲区则先放于临时目录中 30 String tempPath = "E:\\tempPath"; 31 System.out.println("临时文件存放位置:"+tempPath); 32 33 34 //判断存放上传文件的目录是否存在(不存在则创建) 35 File f = new File(realPath); 36 if(!f.exists()&&!f.isDirectory()){ 37 System.out.println("目录或文件不存在! 创建目标目录。"); 38 f.mkdir(); 39 } 40 //判断临时目录是否存在(不存在则创建) 41 File f1 = new File(tempPath); 42 if(!f1.isDirectory()){ 43 System.out.println("临时文件目录不存在! 创建临时文件目录"); 44 f1.mkdir(); 45 } 46 47 /** 48 * 使用Apache文件上传组件处理文件上传步骤: 49 * 50 * */ 51 //1、设置环境:创建一个DiskFileItemFactory工厂 52 DiskFileItemFactory factory = new DiskFileItemFactory(); 53 54 //设置上传文件的临时目录 55 factory.setRepository(f1); 56 57 //2、核心操作类:创建一个文件上传解析器。 58 ServletFileUpload upload = new ServletFileUpload(factory); 59 //解决上传"文件名"的中文乱码 60 upload.setHeaderEncoding("UTF-8"); 61 62 //3、判断enctype:判断提交上来的数据是否是上传表单的数据 63 if(!ServletFileUpload.isMultipartContent(req)){ 64 System.out.println("不是上传文件,终止"); 65 //按照传统方式获取数据 66 return; 67 } 68 69 //==获取输入项== 70 // //限制单个上传文件大小(5M) 71 // upload.setFileSizeMax(1024*1024*4); 72 // //限制总上传文件大小(10M) 73 // upload.setSizeMax(1024*1024*6); 74 75 //4、使用ServletFileUpload解析器解析上传数据,解析结果返回的是一个List<FileItem>集合,每一个FileItem对应一个Form表单的输入项 76 List<FileItem> items =upload.parseRequest(req); 77 for(FileItem item:items){ 78 //如果fileitem中封装的是普通输入项的数据(输出名、值) 79 if(item.isFormField()){ 80 String filedName = item.getFieldName();//普通输入项数据的名 81 //解决普通输入项的数据的中文乱码问题 82 String filedValue = item.getString("UTF-8");//普通输入项的值 83 System.out.println("普通字段:"+filedName+"=="+filedValue); 84 }else{ 85 //如果fileitem中封装的是上传文件,得到上传的文件名称, 86 String fileName = item.getName();//上传文件的名 87 //多个文件上传输入框有空 的 异常处理 88 if(fileName==null||"".equals(fileName.trim())){ //去空格是否为空 89 continue;// 为空,跳过当次循环, 第一个没输入则跳过可以继续输入第二个 90 } 91 92 //注意:不同的浏览器提交的文件名是不一样的,有些浏览器提交上来的文件名是带有路径的,如: c:\a\b\1.txt,而有些只是单纯的文件名,如:1.txt 93 //处理上传文件的文件名的路径,截取字符串只保留文件名部分。//截取留最后一个"\"之后,+1截取向右移一位("\a.txt"-->"a.txt") 94 fileName = fileName.substring(fileName.lastIndexOf("\\")+1); 95 //拼接上传路径。存放路径+上传的文件名 96 String filePath = realPath+"\\"+fileName; 97 //构建输入输出流 98 InputStream in = item.getInputStream(); //获取item中的上传文件的输入流 99 OutputStream out = new FileOutputStream(filePath); //创建一个文件输出流 100 101 //创建一个缓冲区 102 byte b[] = new byte[1024]; 103 //判断输入流中的数据是否已经读完的标识 104 int len = -1; 105 //循环将输入流读入到缓冲区当中,(len=in.read(buffer))!=-1就表示in里面还有数据 106 while((len=in.read(b))!=-1){ //没数据了返回-1 107 //使用FileOutputStream输出流将缓冲区的数据写入到指定的目录(savePath+"\\"+filename)当中 108 out.write(b, 0, len); 109 } 110 //关闭流 111 out.close(); 112 in.close(); 113 //删除临时文件 114 try { 115 Thread.sleep(3000); 116 } catch (InterruptedException e) { 117 e.printStackTrace(); 118 } 119 item.delete();//删除处理文件上传时生成的临时文件 120 System.out.println("文件上传成功"); 121 } 122 } 123 } catch (FileUploadException e) { 124 //e.printStackTrace(); 125 throw new RuntimeException("服务器繁忙,文件上传失败"); 126 } 127 } 128 129 @Override 130 protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 131 this.doPost(req, resp); 132 }