Java 文件传输原理及介绍

Java 文件传输原理及介绍

1.搭建环境(不使用Maven)

在这里插入图片描述

2.导入必要的包

在根目录下创建lib,maven库下载jar包并导入

https://mvnrepository.com/artifact/commons-io/commons-io

https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload

在这里插入图片描述

注意项目结构处的:Problem:点击 [fix] —— 保证自己添加的 jar 包也能在 Artifact 输出中

3.文件上传原理

在这里插入图片描述

可以打开cmd,ping域名获得域名对应公网IP地址

4.上传文件调优

在这里插入图片描述

为避免同名图片的出现可以使用MD5加密还有uid,时间戳等等

5.代码解析

 import org.apache.commons.fileupload.FileItem;
 import org.apache.commons.fileupload.FileUploadException;
 import org.apache.commons.fileupload.ProgressListener;
 import org.apache.commons.fileupload.disk.DiskFileItemFactory;
 import org.apache.commons.fileupload.servlet.ServletFileUpload;
 
 import javax.servlet.ServletException;
 import javax.servlet.annotation.WebServlet;
 import javax.servlet.http.HttpServlet;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 import java.io.File;
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.util.List;
 import java.util.UUID;
 
 @WebServlet(name = "FileServlet")
 public class FileServlet extends HttpServlet {
     private static final long serialVersionUID = 1L;
 
     protected void doPost(HttpServletRequest request, HttpServletResponse response)
             throws ServletException, IOException {
         // TODO Auto-generated method stub
         // response.getWriter().append("Served at: ").append(request.getContextPath());
 
         // 判断上传的文件普通表单还是带文件的表单
         if (!ServletFileUpload.isMultipartContent(request)) {
             return;//终止方法运行,说明这是一个普通的表单,直接返回
        }
         //创建上传文件的保存路径,建议在WEB-INF路径下,安全,用户无法直接访间上传的文件;
         String uploadPath =this.getServletContext().getRealPath("/WEB-INF/upload");
         File uploadFile = new File(uploadPath);
         if (!uploadFile.exists()){
             uploadFile.mkdir(); //创建这个月录
        }
 
         // 创建上传文件的保存路径,建议在WEB-INF路径下,安全,用户无法直接访问上传的文件
         String tmpPath = this.getServletContext().getRealPath("/WEB-INF/tmp");
         File file = new File(tmpPath);
         if (!file.exists()) {
             file.mkdir();//创建临时目录
        }
 
         // 处理上传的文件,一般都需要通过流来获取,我们可以使用 request, getInputstream(),原生态的文件上传流获取,十分麻烦
         // 但是我们都建议使用 Apache的文件上传组件来实现, common-fileupload,它需要旅 commons-io组件;
         try {
             // 创建DiskFileItemFactory对象,处理文件路径或者大小限制
             DiskFileItemFactory factory = getDiskFileItemFactory(file);
             /*
              * //通过这个工厂设置一个缓冲区,当上传的文件大于这个缓冲区的时候,将他放到临时文件 factory.setSizeThreshold(1024 *
              * 1024); //缓存区大小为1M factory.setRepository (file);//临时目录的保存目录,需要一个File
              */
 
             // 2、获取ServletFileUpload
             ServletFileUpload upload = getServletFileUpload(factory);
 
             // 3、处理上传文件
             // 把前端请求解析,封装成FileItem对象,需要从ServletFileUpload对象中获取
             String msg = uploadParseRequest(upload, request, uploadPath);
 
             // Servlet请求转发消息
             System.out.println(msg);
             if(msg.equals("文件上传成功!")) {
                 // Servlet请求转发消息
                 request.setAttribute("msg",msg);
                 request.getRequestDispatcher("info.jsp").forward(request, response);
            }else {
                 msg ="请上传文件";
                 request.setAttribute("msg",msg);
                 request.getRequestDispatcher("info.jsp").forward(request, response);
            }
 
        } catch (FileUploadException e) {
             // TODO 自动生成的 catch 块
             e.printStackTrace();
        }
    }
 
     public static DiskFileItemFactory getDiskFileItemFactory(File file) {
         DiskFileItemFactory factory = new DiskFileItemFactory();
         // 通过这个工厂设置一个缓冲区,当上传的文件大于这个缓冲区的时候,将他放到临时文件中;
         factory.setSizeThreshold(1024 * 1024);// 缓冲区大小为1M
         factory.setRepository(file);// 临时目录的保存目录,需要一个file
         return factory;
    }
 
     public static ServletFileUpload getServletFileUpload(DiskFileItemFactory factory) {
         ServletFileUpload upload = new ServletFileUpload(factory);
         // 监听长传进度
         upload.setProgressListener(new ProgressListener() {
 
             // pBYtesRead:已读取到的文件大小
             // pContextLength:文件大小
             public void update(long pBytesRead, long pContentLength, int pItems) {
                 System.out.println("总大小:" + pContentLength + "已上传:" + pBytesRead);
            }
        });
 
         // 处理乱码问题
         upload.setHeaderEncoding("UTF-8");
         // 设置单个文件的最大值
         upload.setFileSizeMax(1024 * 1024 * 10);
         // 设置总共能够上传文件的大小
         // 1024 = 1kb * 1024 = 1M * 10 = 10м
 
         return upload;
    }
 
     public static String uploadParseRequest(ServletFileUpload upload, HttpServletRequest request, String uploadPath)
             throws FileUploadException, IOException {
 
         String msg = "";
 
         // 把前端请求解析,封装成FileItem对象
         List<FileItem> fileItems = upload.parseRequest(request);
         for (FileItem fileItem : fileItems) {
             if (fileItem.isFormField()) {// 判断上传的文件是普通的表单还是带文件的表单
                 // getFieldName指的是前端表单控件的name;
                 String name = fileItem.getFieldName();
                 String value = fileItem.getString("UTF-8"); // 处理乱码
                 System.out.println(name + ": " + value); 
          } else {// 判断它是上传的文件 
​ 
               // ============处理文件============== 
​ 
               // 拿到文件名 
               String uploadFileName = fileItem.getName(); 
               System.out.println("上传的文件名: " + uploadFileName); 
               if (uploadFileName.trim().equals("") || uploadFileName == null) { 
                   continue; 
              } 
​ 
               // 获得上传的文件名/images/girl/paojie.png 
               String fileName = uploadFileName.substring(uploadFileName.lastIndexOf("/") + 1); 
               // 获得文件的后缀名 
               String fileExtName = uploadFileName.substring(uploadFileName.lastIndexOf(".") + 1); 
​ 
               /* 
                * 如果文件后缀名fileExtName不是我们所需要的 就直按return.不处理,告诉用户文件类型不对。 
                */ 
​ 
               System.out.println("文件信息[件名: " + fileName + " ---文件类型" + fileExtName + "]"); 
               // 可以使用UID(唯一识别的通用码),保证文件名唯 
               // 0UID. randomUUID(),随机生一个唯一识别的通用码; 
               String uuidPath = UUID.randomUUID().toString(); 
​ 
               // ================处理文件完毕============== 
​ 
               // 存到哪? uploadPath 
               // 文件真实存在的路径realPath 
               String realPath = uploadPath + "/" + uuidPath; 
               // 给每个文件创建一个对应的文件夹 
               File realPathFile = new File(realPath); 
               if (!realPathFile.exists()) { 
                   realPathFile.mkdir(); 
              } 
               // ==============存放地址完毕============== 
​ 
​ 
               // 获得文件上传的流 
               InputStream inputStream = fileItem.getInputStream(); 
               // 创建一个文件输出流 
               // realPath =真实的文件夹; 
               // 差了一个文件;加上翰出文件的名产"/"+uuidFileName 
               FileOutputStream fos = new FileOutputStream(realPath + "/" + fileName); 
               System.out.println("path:"+realPath + "/" + fileName); 
               // 创建一个缓冲区 
               byte[] buffer = new byte[1024 * 1024]; 
               // 判断是否读取完毕 
               int len = 0; 
               // 如果大于0说明还存在数据; 
               while ((len = inputStream.read(buffer)) > 0) { 
                   fos.write(buffer, 0, len); 
              } 
               // 关闭流 
               fos.close(); 
               inputStream.close(); 
​ 
               msg = "文件上传成功!"; 
               fileItem.delete(); // 上传成功,清除临时文件 
               //=============文件传输完成============= 
          } 
      } 
       return msg; 
​ 
  } 
}

6.笔记

1、 form 表单提交时, method 为 get 的话,上传文件大小会有限制

2、文件真正上传成功的地方,是项目 Aritifact 下的 output directory ,具有安全性。而不是 IDEA 项目文件路径

3、 float f = 0.1 f != double d = 0.1/10 离散,大约数

4、所以需要用 BigDecimal 更为精确

posted @   星羽恒  阅读(352)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
点击右上角即可分享
微信分享提示