Java Servlet 上传文件
最后修改于 2023 年 8 月 24 日
Java Servlet 上传文件演示了如何使用 Servlet 技术在 Java Web 应用程序中上传单个文件。
Java Servlet
Servlet 是一个 Java 类,它响应特定类型的网络请求——最常见的是 HTTP 请求。Java Servlet 用于创建 Web 应用程序。它们运行在 Tomcat 或 Jetty 等 Servlet 容器中。现代 Java Web 开发使用构建在 Servlet 之上的框架。
HTML 表单编码类型
POST 请求有三种编码 HTML 表单的方法:
- application/x-www-form-urlencoded
- multipart/form-data
- text/plain
application/x-www-form-urlencoded
是默认编码。值被编码为由 &
分隔的键值对。键和值之间使用 =
字符。非字母数字字符会被百分比编码。此编码类型不适用于二进制文件。
multipart/form-data
用于非 ASCII 数据和二进制文件。input
元素的 type
属性设置为 file
。
text/plain
用于调试。
Java Servlet 上传文件示例
在以下应用程序中,我们有一个 Web 表单用于选择要上传到服务器的文件。该表单调用一个 Java Servlet,该 Servlet 读取文件并将其保存在目录中。
上传目录
/var/www/
目录是 Debian Linux 中 Web 内容的标准目录。
$ ls -ld /var/www/upload/ drwxr-xr-x 2 www-data www-data 4096 Jul 24 11:36 /var/www/upload/
我们将把文件上传到 /var/www/upload/
目录。该目录文件可以由属于 www-data
组的用户修改。因此,运行 Web 服务器的用户必须属于此组。
应用程序
这是一个 Maven Web 应用程序;它部署在嵌入式 Jetty 服务器上。
pom.xml src ├── main │ ├── java │ │ └── com │ │ └── zetcode │ │ └── web │ │ └── UploadFile.java │ ├── resources │ └── webapp │ └── index.html └── test └── java
这是项目结构。
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.zetcode</groupId> <artifactId>JavaServletUploadFile</artifactId> <version>1.0-SNAPSHOT</version> <packaging>war</packaging> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.source>14</maven.compiler.source> <maven.compiler.target>14</maven.compiler.target> </properties> <dependencies> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>4.0.1</version> <scope>provided</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-war-plugin</artifactId> <version>3.3.0</version> </plugin> <plugin> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-maven-plugin</artifactId> <version>9.4.30.v20200611</version> </plugin> </plugins> </build> </project>
这是 Maven POM 文件。javax.servlet-api
伪像是用于 Servlet 的。
maven-war-plugin
负责收集 Web 应用程序的所有伪像依赖项、类和资源,并将它们打包成 Web 应用程序档案 (WAR)。jetty-maven-plugin
是一个用于快速开发和测试的有用 Maven 插件。它创建一个 Web 应用程序,启动一个 Jetty Web 服务器,并将应用程序部署到服务器上。
package com.zetcode.web; import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.ServletOutputStream; import javax.servlet.annotation.MultipartConfig; import javax.servlet.annotation.WebInitParam; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.Part; import java.io.IOException; import java.io.InputStream; import java.nio.file.Files; import java.nio.file.Paths; import java.nio.file.StandardCopyOption; @WebServlet(name = "UploadFile", urlPatterns = {"/UploadFile"}, initParams = { @WebInitParam(name = "uploadpath", value = "/var/www/upload/") }) @MultipartConfig public class UploadFile extends HttpServlet { @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { response.setContentType("text/plain;charset=UTF-8"); ServletOutputStream os = response.getOutputStream(); ServletConfig sc = getServletConfig(); String path = sc.getInitParameter("uploadpath"); Part filePart = request.getPart("myfile"); String fileName = filePart.getSubmittedFileName(); InputStream is = filePart.getInputStream(); Files.copy(is, Paths.get(path + fileName), StandardCopyOption.REPLACE_EXISTING); os.print("File successfully uploaded"); } }
UploadFile
将文件上传到 /var/www/upload/
目录。
@WebServlet(name = "UploadFile", urlPatterns = {"/UploadFile"}, initParams = { @WebInitParam(name = "uploadpath", value = "/var/www/upload/") })
使用 @WebServlet
注解,我们将 Servlet 映射到 /UploadFile
URL 模式,并定义一个初始的 uploadpath
变量。
@MultipartConfig
Servlet 还用 @MultipartConfig
进行装饰。@MultipartConfig
注解表示 Servlet 期望使用 multipart/form-data
MIME 类型进行请求。
@Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
POST 请求由 doPost()
方法处理。
ServletOutputStream os = response.getOutputStream();
我们使用 getOutputStream()
方法获取 Servlet 输出流。
ServletConfig sc = getServletConfig(); String path = sc.getInitParameter("uploadpath");
我们检索初始参数。这是我们要上传文件的目录。
Part filePart = request.getPart("myfile");
文件部分通过 getPart()
方法检索。
String fileName = filePart.getSubmittedFileName(); InputStream is = filePart.getInputStream();
我们获取部分的文件名和输入流。
Files.copy(is, Paths.get(path + fileName), StandardCopyOption.REPLACE_EXISTING);
使用 Files.copy()
,我们将文件复制到目标目录。
os.print("File successfully uploaded");
最后,我们向客户端写回一条消息。
<!DOCTYPE html> <html> <head> <title>Uploading a file</title> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <link rel="stylesheet" href="https://unpkg.com/purecss@2.0.3/build/pure-min.css" crossorigin="anonymous"> <style> main { margin:1em } </style> </head> <body> <main> <form class="pure-form pure-form-stacked" method="post" action="UploadFile" enctype="multipart/form-data"> <fieldset> <legend>File:</legend> <input type="file" name="myfile"> <button type="submit" class="pure-button pure-button-primary">Upload</button> </fieldset> </form> </main> </body> </html>
这是用于选择要上传文件的首页。它包含一个 HTML 表单。提交表单后,处理被发送到 UploadFile
。
<link rel="stylesheet" href="https://unpkg.com/purecss@2.0.3/build/pure-min.css" crossorigin="anonymous">
我们包含了 Pure.css 库,用于创建响应式页面。
<form class="pure-form pure-form-stacked" method="post" action="UploadFile" enctype="multipart/form-data">
method
属性为 post,因为我们将数据发送到服务器。action
属性指定了处理请求的 Servlet 的名称。enctype
属性指定了 multipart/form-data
编码类型,这对于使用 HTML 表单上传文件是必需的。
<input type="file" name="myfile">
input
标签的 type
属性允许用户选择单个文件。
<button type="submit" class="pure-button pure-button-primary">Upload</button>
这是提交按钮。
在本文中,我们展示了如何使用 Java Servlet 上传单个文件。