文件上传的场景
文件上传,是程序开发中必须会使用到一个功能,比如:
1:添加商品,用户头像,文章封面等需求。
2:富文本编辑(附件件文件上传)。
文件上传的原理
文件上传的原理就是共享资源,大家都可以看你的在平台上上传的文件。也就是把用户的自己电脑中的文件通过程序上传到服务器的过程。
准备工作
文件上传需要jar包:commons-fileupload,commons-io
在pom.xml文件添加如下代码
1 <!-- https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload --> 2 <dependency> 3 <groupId>commons-fileupload</groupId> 4 <artifactId>commons-fileupload</artifactId> 5 <version>1.4</version> 6 </dependency> 7 <!-- https://mvnrepository.com/artifact/commons-io/commons-io --> 8 <dependency> 9 <groupId>commons-io</groupId> 10 <artifactId>commons-io</artifactId> 11 <version>2.6</version> 12 </dependency>
添加web支持,并编写index.jsp文件
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <body> <%-- GET:上传文件大小有限制 POST:上传文件大小没有限制 ${pageContext.request.contextPath} --%> <form action="upload.do" enctype="multipart/form-data" method="post"> 上传用户:<input type="text" name="username"><br/> <P><input type="file" name="file1"></P> <P><input type="file" name="file1"></P> <P><input type="submit" value="提交"> | <input type="reset"></P> </form> </body> </html>
解释
1:对于post请求来说:
数据量大小:
原则上post是默认无限制的,多大的数据都可以请求,
2:get请求限制
理论上GET请求数据长度没有限制的,真正起到限制的是浏览器对其长度进行了限制。
Google (chrome):URL最大长度限制为8182个字符。
Firefox (Browser):URL的长度限制为65,536个字符。
info.jsp页面
<%@ page language="java" contentType="text/html;charset=UTF-8"%> <!DOCTYPE html> <html> <head> <title>Insert title here</title> </head> <body> <%=request.getAttribute("msg")%> </body> </html>
先在web.xml中注册servlet
<servlet> <servlet-name>upload</servlet-name> <servlet-class>com.wang.FileSerlvet</servlet-class> </servlet> <servlet-mapping> <servlet-name>upload</servlet-name> <url-pattern>/upload.do</url-pattern> </servlet-mapping>
编写文件上传FileServlet类
1 public class FileSerlvet extends HttpServlet { 2 private static final long serialVersionUID = 1L; 7 protected void doPost(HttpServletRequest request, HttpServletResponse response) 8 throws ServletException, IOException { 11 // 判断上传的文件普通表单还是带文件的表单 12 if (!ServletFileUpload.isMultipartContent(request)) { 13 return;//终止方法运行,说明这是一个普通的表单,直接返回 14 } 15 //创建上传文件的保存路径,建议在WEB-INF路径下,安全,用户无法直接访间上传的文件; 16 String uploadPath =this.getServletContext().getRealPath("/WEB-INF/upload"); 17 File uploadFile = new File(uploadPath); 18 if (!uploadFile.exists()){ 19 uploadFile.mkdir(); //创建这个月录 20 } 21 // 创建上传文件的保存路径,建议在WEB-INF路径下,安全,用户无法直接访问上传的文件 22 String tmpPath = this.getServletContext().getRealPath("/WEB-INF/tmp"); 23 File file = new File(tmpPath); 24 if (!file.exists()) { 25 file.mkdir();//创建临时目录 26 } 27 // 处理上传的文件,一般都需要通过流来获取,我们可以使用 request, getInputstream(),原生态的文件上传流获取,十分麻烦 28 // 但是我们都建议使用 Apache的文件上传组件来实现, common-fileupload,它需要旅 commons-io组件; 29 try { 30 // 创建DiskFileItemFactory对象,处理文件路径或者大小限制 31 DiskFileItemFactory factory = getDiskFileItemFactory(file); 32 /* 33 * //通过这个工厂设置一个缓冲区,当上传的文件大于这个缓冲区的时候,将他放到临时文件 factory.setSizeThreshold(1024 * 34 * 1024); //缓存区大小为1M factory.setRepository (file);//临时目录的保存目录,需要一个File 35 */ 36 // 2、获取ServletFileUpload 37 ServletFileUpload upload = getServletFileUpload(factory); 38 // 3、处理上传文件 39 // 把前端请求解析,封装成FileItem对象,需要从ServletFileUpload对象中获取 40 String msg = uploadParseRequest(upload, request, uploadPath); 41 // Servlet请求转发消息 42 System.out.println(msg); 43 if(msg == "文件上传成功!") { 44 // Servlet请求转发消息 45 request.setAttribute("msg",msg); 46 request.getRequestDispatcher("info.jsp").forward(request, response); 47 }else { 48 msg ="请上传文件"; 49 request.setAttribute("msg",msg); 50 request.getRequestDispatcher("info.jsp").forward(request, response); 51 } 52 } catch (FileUploadException e) { 53 // TODO 自动生成的 catch 块 54 e.printStackTrace(); 55 } 56 } 57 public static DiskFileItemFactory getDiskFileItemFactory(File file) { 58 DiskFileItemFactory factory = new DiskFileItemFactory(); 59 // 通过这个工厂设置一个缓冲区,当上传的文件大于这个缓冲区的时候,将他放到临时文件中; 60 factory.setSizeThreshold(1024 * 1024);// 缓冲区大小为1M 61 factory.setRepository(file);// 临时目录的保存目录,需要一个file 62 return factory; 63 } 64 public static ServletFileUpload getServletFileUpload(DiskFileItemFactory factory) { 65 ServletFileUpload upload = new ServletFileUpload(factory); 66 // 监听长传进度 67 upload.setProgressListener(new ProgressListener() { 68 // pBYtesRead:已读取到的文件大小 69 // pContextLength:文件大小 70 public void update(long pBytesRead, long pContentLength, int pItems) { 71 System.out.println("总大小:" + pContentLength + "已上传:" + pBytesRead); 72 } 73 }); 74 // 处理乱码问题 75 upload.setHeaderEncoding("UTF-8"); 76 // 设置单个文件的最大值 77 upload.setFileSizeMax(1024 * 1024 * 10); 78 // 设置总共能够上传文件的大小 79 // 1024 = 1kb * 1024 = 1M * 10 = 10м 80 return upload; 81 } 82 public static String uploadParseRequest(ServletFileUpload upload, HttpServletRequest request, String uploadPath) 83 throws FileUploadException, IOException { 84 String msg = ""; 85 // 把前端请求解析,封装成FileItem对象 86 List<FileItem> fileItems = upload.parseRequest(request); 87 for (FileItem fileItem : fileItems) { 88 if (fileItem.isFormField()) {// 判断上传的文件是普通的表单还是带文件的表单 89 // getFieldName指的是前端表单控件的name; 90 String name = fileItem.getFieldName(); 91 String value = fileItem.getString("UTF-8"); // 处理乱码 92 System.out.println(name + ": " + value); 93 } else {// 判断它是上传的文件 94 // ============处理文件============== 95 // 拿到文件名 96 String uploadFileName = fileItem.getName(); 97 System.out.println("上传的文件名: " + uploadFileName); 98 if (uploadFileName.trim().equals("") || uploadFileName == null) { 99 continue; 100 } 101 // 获得上传的文件名/images/girl/paojie.png 102 String fileName = uploadFileName.substring(uploadFileName.lastIndexOf("/") + 1); 103 // 获得文件的后缀名 104 String fileExtName = uploadFileName.substring(uploadFileName.lastIndexOf(".") + 1); 105 /* 106 * 如果文件后缀名fileExtName不是我们所需要的 就直按return.不处理,告诉用户文件类型不对。 107 */ 108 System.out.println("文件信息[件名: " + fileName + " ---文件类型" + fileExtName + "]"); 109 // 可以使用UID(唯一识别的通用码),保证文件名唯 110 // 0UID. randomUUID(),随机生一个唯一识别的通用码; 111 String uuidPath = UUID.randomUUID().toString(); 112 // ================处理文件完毕============== 113 // 存到哪? uploadPath 114 // 文件真实存在的路径realPath 115 String realPath = uploadPath + "/" + uuidPath; 116 // 给每个文件创建一个对应的文件夹 117 File realPathFile = new File(realPath); 118 if (!realPathFile.exists()) { 119 realPathFile.mkdir(); 120 } 121 // ==============存放地址完毕============== 122 // 获得文件上传的流 123 InputStream inputStream = fileItem.getInputStream(); 124 // 创建一个文件输出流 125 // realPath =真实的文件夹; 126 // 差了一个文件;加上翰出文件的名产"/"+uuidFileName 127 FileOutputStream fos = new FileOutputStream(realPath + "/" + fileName); 128 // 创建一个缓冲区 129 byte[] buffer = new byte[1024 * 1024]; 130 // 判断是否读取完毕 131 int len = 0; 132 // 如果大于0说明还存在数据; 133 while ((len = inputStream.read(buffer)) > 0) { 134 fos.write(buffer, 0, len); 135 } 136 // 关闭流 137 fos.close(); 138 inputStream.close(); 139 msg = "文件上传成功!"; 140 fileItem.delete(); // 上传成功,清除临时文件 141 //=============文件传输完成============= 142 } 143 } 144 return msg; 145 }