首页 › 问答 › Java › 正文 Java Servlet 如何实现文件上传和下载? 2026-05-04 10:30:40 约 1 分钟读完 29 阅 文章导读 Servlet 上传文件 我们的使用场景是提供一个简单的 HTML 页面,客户端可以选择本地文件上传到服务器。在提交上传文件请求时,我们的 servlet 程序会将文件上传到服务器上的一个目录中,然后提供用户可以下载文件的 URL。出于安全考虑,不会直接向用户提供下载文件的 URL,而是给他们一个下载链接,我们的 servlet 会处理该请求并将文件发送给用户。我们将在 Eclipse 中创建一 📋 目录 一 Servlet 上传文件 二 文件上传下载 Servlet A A 博客文档招聘获取支持联系销售Servlet 上传文件 我们的使用场景是提供一个简单的 HTML 页面,客户端可以选择本地文件上传到服务器。在提交上传文件请求时,我们的 servlet 程序会将文件上传到服务器上的一个目录中,然后提供用户可以下载文件的 URL。出于安全考虑,不会直接向用户提供下载文件的 URL,而是给他们一个下载链接,我们的 servlet 会处理该请求并将文件发送给用户。我们将在 Eclipse 中创建一个动态 Web 项目,项目结构如下图所示。让我们来看看 Web 应用程序的所有组件并了解实现方式。 用于 Java 上传文件到服务器的 HTML 页面 我们可以通过向 servlet 发送 POST 请求并提交表单来将文件上传到服务器。上传文件不能使用 GET 方法。另一个需要注意的点是表单的 enctype 应该是 multipart/form-data。要从用户文件系统中选择文件,我们需要使用 type 为 file 的 input 元素。因此,我们可以有一个简单的 HTML 页面 index.html 用于上传文件,如下所示: <html> <head></head> <body> <form action="UploadDownloadFileServlet" method="post" enctype="multipart/form-data"> Select File to Upload:<input type="file" name="fileName"> <br> <input type="submit" value="Upload"> </form> </body> </html> 文件上传的服务器文件位置 我们需要将文件存储到服务器上的某个目录中,可以在程序中硬编码该目录,但为了更好的灵活性,我们将在部署描述符的 context params 中配置它。另外,我们还会将上传文件的 HTML 页面添加到欢迎文件列表中。我们的 web.xml 文件如下所示: <?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xmlns="https://java.sun.com/xml/ns/javaee" xsi:schemaLocation="https://java.sun.com/xml/ns/javaee https://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0"> <display-name>ServletFileUploadDownloadExample</display-name> <welcome-file-list> <welcome-file>index.html</welcome-file> </welcome-file-list> <context-param> <param-name>tempfile.dir</param-name> <param-value>tmpfiles</param-value> </context-param> </web-app> 用于文件上传位置的 ServletContextListener 由于我们需要读取文件位置的 context parameter 并从中创建 File 对象,我们可以编写一个 ServletContextListener,在 context 初始化时执行此操作。我们可以将绝对目录位置和 File 对象设置为 context attribute,供其他 servlet 使用。我们的 ServletContextListener 实现代码如下所示。 package com.journaldev.servlet; import java.io.File; import javax.servlet.ServletContext; import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener; import javax.servlet.annotation.WebListener; @WebListener public class FileLocationContextListener implements ServletContextListener { public void contextInitialized(ServletContextEvent servletContextEvent) { String rootPath = System.getProperty("catalina.home"); ServletContext ctx = servletContextEvent.getServletContext(); String relativePath = ctx.getInitParameter("tempfile.dir"); File file = new File(rootPath + File.separator + relativePath); if(!file.exists()) file.mkdirs(); System.out.println("文件目录已创建,用于存储文件"); ctx.setAttribute("FILES_DIR_FILE", file); ctx.setAttribute("FILES_DIR", rootPath + File.separator + relativePath); } public void contextDestroyed(ServletContextEvent servletContextEvent) { //如需清理则执行 } } 文件上传下载 Servlet 更新:Servlet Specs 3 在 API 中添加了对服务器端文件上传的支持,因此我们无需使用任何第三方 API。请查看 Servlet 3 Upload File。对于文件上传,我们将使用 Apache Commons FileUpload 工具,对于我们的项目,我们使用的是 1.3 版本,FileUpload 依赖于 Apache Commons IO jar,因此我们需要将两者都放在项目的 lib 目录中,如上图所示的项目结构。我们将使用 DiskFileItemFactory 工厂,它提供了一个方法来解析 HttpServletRequest 对象并返回 FileItem 列表。FileItem 提供了有用的方法来获取文件名、表单中的字段名、大小以及需要上传的文件的 content type 详情。要将文件写入目录,我们只需创建一个 File 对象并将其作为参数传递给 FileItem 的 write() 方法。由于 servlet 的整个目的是上传文件,我们将重写 init() 方法来初始化 servlet 的 DiskFileItemFactory 对象实例。我们将在 doPost() 方法实现中使用此对象将文件上传到服务器目录。一旦文件成功上传,我们将向客户端发送带有文件下载 URL 的响应,由于 HTML 链接使用 GET 方法,我们将在 URL 中附加文件名参数,并利用同一个 servlet 的 doGet() 方法来实现文件下载过程。对于实现下载文件 servlet,首先我们将为文件打开 InputStream,并使用 ServletContext.getMimeType() 方法获取文件的 MIME 类型并将其设置为响应 content type。我们还需要将响应 content length 设置为文件长度。为了确保客户端理解我们正在响应中发送文件,我们需要设置 “Content-Disposition” 标头,其值为 "attachment; filename=“fileName”。完成响应配置后,我们可以从 InputStream 读取文件内容并写入 ServletOutputStream,然后将输出刷新到客户端。我们最终的 UploadDownloadFileServlet servlet 实现如下所示。 package com.journaldev.servlet; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.PrintWriter; import java.util.Iterator; import java.util.List; import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.ServletOutputStream; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.fileupload.FileItem; import org.apache.commons.fileupload.FileUploadException; import org.apache.commons.fileupload.disk.DiskFileItemFactory; import org.apache.commons.fileupload.servlet.ServletFileUpload; @WebServlet("/UploadDownloadFileServlet") public class UploadDownloadFileServlet extends HttpServlet { private static final long serialVersionUID = 1L; private ServletFileUpload uploader = null; @Override public void init() throws ServletException{ DiskFileItemFactory fileFactory = new DiskFileItemFactory(); File filesDir = (File) getServletContext().getAttribute("FILES_DIR_FILE"); fileFactory.setRepository(filesDir); this.uploader = new ServletFileUpload(fileFactory); } protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String fileName = request.getParameter("fileName"); if(fileName == null || fileName.equals("")){ throw new ServletException("File Name can't be null or empty"); } File file = new File(request.getServletContext().getAttribute("FILES_DIR")+File.separator+fileName); if(!file.exists()){ throw new ServletException("File doesn't exists on server."); } System.out.println("服务器上的文件位置::"+file.getAbsolutePath()); ServletContext ctx = getServletContext(); InputStream fis = new FileInputStream(file); String mimeType = ctx.getMimeType(file.getAbsolutePath()); response.setContentType(mimeType != null? mimeType:"application/octet-stream"); response.setContentLength((int) file.length()); response.setHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\""); ServletOutputStream os = response.getOutputStream(); byte[] bufferData = new byte[1024]; int read=0; while((read = fis.read(bufferData))!= -1){ os.write(bufferData, 0, read); } os.flush(); os.close(); fis.close(); System.out.println("文件已成功下载到客户端"); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { if(!ServletFileUpload.isMultipartContent(request)){ throw new ServletException("Content type is not multipart/form-data"); } response.setContentType("text/html"); PrintWriter out = response.getWriter(); out.write("<html><head></head><body>"); try { List<FileItem> fileItemsList = uploader.parseRequest(request); Iterator<FileItem> fileItemsIterator = fileItemsList.iterator(); while(fileItemsIterator.hasNext()){ FileItem fileItem = fileItemsIterator.next(); System.out.println("FieldName="+fileItem.getFieldName()); System.out.println("FileName="+fileItem.getName()); System.out.println("ContentType="+fileItem.getContentType()); System.out.println("Size in bytes="+fileItem.getSize()); File file = new File(request.getServletContext().getAttribute("FILES_DIR")+File.separator+fileItem.getName()); System.out.println("服务器上的绝对路径="+file.getAbsolutePath()); fileItem.write(file); out.write("文件 "+fileItem.getName()+ " 上传成功。"); out.write("<br>"); out.write("<a href=\"UploadDownloadFileServlet?fileName="+fileItem.getName()+"\">下载 "+fileItem.getName()+"</a>"); } } catch (FileUploadException e) { out.write("上传文件时发生异常。"); } catch (Exception e) { out.write("上传文件时发生异常。"); } out.write("</body></html>"); } } 项目的示例执行结果如下图所示。 下载 Servlet 文件上传下载项目 您可以从以下 URL 下载 Apache Commons IO jar 和 Apache Commons FileUpload jar。https://commons.apache.org/proper/commons-fileupload/download_fileupload.cgihttps://commons.apache.org/proper/commons-io/download_io.cgi 下载 Servlet 文件上传下载示例项目 查看系列文章的下一篇关于 Servlet 异常处理 的内容。 感谢与 Community 一起学习。请查看我们提供的计算、存储、网络和管理数据库产品。 了解更多我们的产品Java