文件上传-java web
第一步:需要引入两个依赖:common-fileupload和commin-io.
第二步.在web页面中添加上传文件的输入项
1.必须使用<input type="file">,并设置input的name属性.
<input type="file" name="file">
2.form表单的enctype必须设置为multipart/form-data.
enctype="multipart/form-data"
3.form表单的提交方式必须是post.
method="post"
第三步.编写servlet,将用户上传的数据保存到本地硬盘.
1.判断用户提交的是否是带文件的表单,如果是普通的表单中止方法运行,直接返回.
if(!ServletFileUpload.isMultipartContent(request)){ return; }
2.创建两个路径,一个文件保存的路径,一个是文件保存的临时路径,防止文件过大占用硬盘空间.
String uploadPath = this.getServletContext().getRealPath("/WEB-INF/upload"); File uploadFile = new File(uploadPath); if (!uploadFile.exists()){ uploadFile.mkdirs(); } String tmpPath = this.getServletContext().getRealPath("/WEB-INF/tmp"); File file = new File(tmpPath); if (!file.exists()){ file.mkdirs(); }
3.创建一个DiskFileItempFactory对象,相当于是一个缓冲区,将过大的文件放入临时路径.(将这个过程封装成方法一,参数是:临时路径,返回DiskFileItempFactory对象)
DiskFileItemFactory factory = getDiskFileItemFactory(file);
4.创建并配置一个ServletFileUpload对象,需要用它来解析前端请求.(将这个过程封装成方法二,参数是:DiskFileItempFactory对象,返回值:ServletFileUpload对象)
ServletFileUpload upload = getServletFileUpload(factory);
5.通过ServletFileUpload对象,将前端请求封装成FileItem对象,FileItem对象可以获取一个输入流,将这个流输出到本地磁盘上,就是用户上传的文件(将这个过程封装成方法三,参数是:ServletFileUpload对象,前端请求,文件保存路径,返回值:执行结果)
String message = uploadParseRequest(upload, request, uploadPath);
6.根据执行结果对前端进行反馈,并跳转页面.
if (Objects.equals(message, "文件上传成功!")){ }else { message = "请上传文件!"; } request.setAttribute("message",message); request.getRequestDispatcher("info.jsp").forward(request,response);
方法一
/** * 上传文件的缓冲区 * @param file 临时文件路径 * @return DiskFileItemFactory对象 */ public static DiskFileItemFactory getDiskFileItemFactory(File file) { //创建一个DiskFileItemFactory对象 DiskFileItemFactory factory = new DiskFileItemFactory(); //设置缓冲区大小为1M factory.setSizeThreshold(1024 * 1024); //设置临时文件的保存路径为方法参数中file factory.setRepository(file); //返回设置好的DiskFileItemFactory对象 return factory; }
方法二
/** * 对创建的ServletFileUpload对象进行配置 * @param factory 缓存区 * @return 配置好的ServletFileUpload对象 */ public static ServletFileUpload getServletFileUpload(DiskFileItemFactory factory) { //创建ServletFileUpload对象,传入设置好的缓存区对象 ServletFileUpload upload = new ServletFileUpload(factory); // 监听上传进度 upload.setProgressListener(new ProgressListener() { public void update(long pBytesRead, long pContentLength, int pItems) { System.out.println("总大小:" + pContentLength + "已上传:" + pBytesRead+",进度:"+((double)pBytesRead/pContentLength)*100+"%"); } }); // 处理编码,防止乱码 upload.setHeaderEncoding("UTF-8"); // 设置单个文件的最大值 upload.setFileSizeMax(1024 * 1024 * 10); //返回ServletFileUpload对象 return upload; }
方法三(核心方法)
/** * 将前端请求中的文件写入本地磁盘 * @param upload ServletFileUpload对象 * @param request 前端请求 * @param uploadPath 本地保存文件的路径 * @return 执行结果 * @throws FileUploadException 文件上传异常 * @throws IOException IO异常 */ public static String uploadParseRequest(ServletFileUpload upload, HttpServletRequest request, String uploadPath) throws FileUploadException, IOException { //创建返回结果 String message = ""; //利用ServletFileUpload对象将前端请求解析并封装成FileItem对象,返回一个FileItem对象集 List<FileItem> fileItems = upload.parseRequest(request); //遍历封装后的FileItem对象 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("")) { continue; } // 获取上传的文件名,将路径去除,只留下 / 后的字符串就是文件自己的名字 例如: C:\Users\lvjianhua\1.jpg String fileName = uploadFileName.substring(uploadFileName.lastIndexOf("/") + 1); // 获得文件的后缀名,将最后一个点后面的字符串获取,来判断文件类型 例如: C:\Users\lvjianhua\1.jpg String fileExtName = uploadFileName.substring(uploadFileName.lastIndexOf(".") + 1); //如果文件后缀名fileExtName不是我们所需要的 就直按return.不处理,告诉用户文件类型不对。 System.out.println("文件信息[件名: " + fileName + " ---文件类型" + fileExtName + "]"); // ================处理文件名完毕============== // ==============处理存放地址开始============== // 可以使用UID(唯一识别的通用码),保证文件名唯一 // UUID.randomUUID(),这个方法可以随机生一个唯一识别的通用码; String uuidPath = UUID.randomUUID().toString(); //用刚才随机生成的UUID和文件保存的路径拼接一个新路径,这个路径就是文件最后存储的路径 String realPath = uploadPath + "/" + uuidPath; //根据这个新路径创建文件夹,每个文件都会有一个单独的文件夹,防止文件重名,发生覆盖, File realPathFile = new File(realPath); //判断文件夹是否存在 if (!realPathFile.exists()) { //不存在就生成一个 realPathFile.mkdir(); } // ==============存放地址完毕============== // =============文件传输开始============= //通过FileItem对象获得文件上传的输入流 InputStream is = fileItem.getInputStream(); //创建输入流,文件路径就是,最终存放地址 + 文件名 FileOutputStream fos = new FileOutputStream(realPath + "/" + fileName); //创建一个缓冲区 byte[] buffer = new byte[1024 * 1024]; //设置一个int值,来储存读取数据的长度 int len = 0; // 一边读,一边写,如果读取的数据长度大于0说明还存在数据,就继续输出 while ((len = is.read(buffer)) > 0) { fos.write(buffer, 0, len); } // 关闭流 fos.close(); is.close(); //执行到此处,说明文件储存成功,给返回结果赋值 message = "文件上传成功!"; //上传成功,清除临时文件 fileItem.delete(); //=============文件传输完毕============= } } //返回执行结果 return message; }
第四步.查看本地磁盘中前端上传的文件
文件上传的四大注意事项:
- 为保证服务器安全,上传的文件应该放在外界无法直接访问的目录下,比如放在WEB-INF目录下
- 为防止上传的文件发生覆盖,要为每一个上传的文件生成一个唯一的文件名
- 限制上传文件的大小
- 限制上传文件的类型,通过文件的后缀名判断是否合法
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· 字符编码:从基础到乱码解决
· 提示词工程——AI应用必不可少的技术