# Java Servlet 上传文件

> 原文： [http://zetcode.com/articles/javaservletuploadfile/](http://zetcode.com/articles/javaservletuploadfile/)

Java Servlet 上传文件显示了如何使用 Servlet 技术在 Java Web 应用中上传单个文件。

## Java Servlet

Servlet 是 Java 类，可响应特定类型的网络请求-最常见的是 HTTP 请求。 Java servlet 用于创建 Web 应用。 它们在 servlet 容器（例如 Tomcat 或 Jetty）中运行。 现代 Java Web 开发使用在 servlet 之上构建的框架。

## HTML 表单编码类型

POST 请求有三种编码 HTML 表单方法：

*   `application/x-www-form-urlencoded`
*   `multipart/form-data`
*   `text/plain`

`application/x-www-form-urlencoded`是默认编码。 这些值编码在由`&`分隔的键值元组中。 `=`字符用于键和值之间。 非字母数字字符采用百分比编码。 此编码类型不适用于二进制文件。

`multipart/form-data`用于非 acsii 数据和二进制文件。 `input`元素的`type`属性设置为`file`。

`text/plain`用于调试。

## Java Servlet 上传文件示例

在以下应用中，我们有一个 Web 表单来选择要上传到服务器的文件。 该表单调用 Java servlet，该 servlet 读取文件并将其保存到目录中。

### 上传目录

`/var/www`目录是 Debian Linux 中 Web 内容的标准目录。

```java
$ ls -ld /var/www/upload/
drwxrwxr-x 2 www-data www-data 4096 Dec  3 14:29 /var/www/upload/

```

我们将文件上传到`/var/www/upload`目录。 `www-data`组中的用户可以修改目录文件。 因此，运行 Web 服务器的用户必须在此组中。

### 应用

这是一个 Maven Web 应用。 它部署在 Tomcat 上。

```java
$ tree
.
├── nb-configuration.xml
├── pom.xml
└── src
    └── main
        ├── java
        │   └── com
        │       └── zetcode
        │           └── FileUploadServlet.java
        └── webapp
            ├── index.html
            └── META-INF
                └── context.xml

```

这是项目结构。

`pom.xml`

```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>JavaServletFileUploadEx</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>war</packaging>

    <name>JavaServletFileUploadEx</name>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
    </properties>

    <dependencies>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.1.0</version>
            <scope>provided</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>

            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-war-plugin</artifactId>
                <version>2.3</version>
                <configuration>
                    <failOnMissingWebXml>false</failOnMissingWebXml>
                </configuration>
            </plugin>

        </plugins>
    </build>

</project>

```

这是 Maven POM 文件。 `javax.servlet-api`工件用于 servlet。 `maven-war-plugin`负责收集 Web 应用的所有工件依赖项，类和资源，并将它们打包到 Web 应用存档（WAR）中。

`context.xml`

```java
<?xml version="1.0" encoding="UTF-8"?>
<Context path="/JavaServletFileUploadEx"/>

```

在 Tomcat `context.xml`文件中，我们定义了上下文路径。 它是 Web 应用的名称。

`FileUploadServlet.java`

```java
package com.zetcode;

import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
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;

@WebServlet(name = "FileUploadServlet", urlPatterns = {"/FileUploadServlet"},
      initParams = { @WebInitParam(name = "path", value = "/var/www/upload/") })
@MultipartConfig
public class FileUploadServlet 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");
    }
}

```

`FileUploadServlet`将文件上传到`/var/www/upload`目录。

```java
@WebServlet(name = "FileUploadServlet", urlPatterns = {"/FileUploadServlet"},
     initParams = { @WebInitParam(name = "uploadpath", value = "/var/www/upload/") })

```

使用`@WebServlet`批注，我们将 servlet 映射到`/FileUploadServlet` URL 模式，并定义了初始的`uploadpath`变量。

```java
@MultipartConfig

```

servlet 也用`@MultipartConfig`装饰。 `@MultipartConfig`批注指示 servlet 期望使用`multipart/form-data` MIME 类型进行请求。

```java
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
        throws IOException, ServletException {

```

POST 请求由`doPost()`方法处理。

```java
ServletOutputStream os = response.getOutputStream();

```

我们使用`getOutputStream()`方法获得 servlet 输出流。

```java
ServletConfig sc = getServletConfig();
String path = sc.getInitParameter("uploadpath");

```

我们检索初始参数。 这是我们要上传文件的目录。

```java
Part filePart = request.getPart("myfile");

```

使用`getPart()`方法检索文件部分。

```java
String fileName = filePart.getSubmittedFileName(); 
InputStream is = filePart.getInputStream();

```

我们得到零件的文件名和输入流。

```java
Files.copy(is, Paths.get(path + fileName),
        StandardCopyOption.REPLACE_EXISTING);

```

使用`Files.copy()`，将文件复制到目标目录。

```java
os.print("File successfully uploaded");

```

最后，我们将消息写回客户端。

`index.html`

```java
<!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@1.0.0/build/pure-min.css">
    </head>
    <body>
        <form class="pure-form pure-form-stacked" method="post" action="FileUploadServlet" 
              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>
    </body>
</html>

```

这是选择要上传文件的主页。 它包含一个 HTML 表单。 提交表单后，处理将发送到`FileUploadServlet`。

```java
<link rel="stylesheet" href="https://unpkg.com/purecss@1.0.0/build/pure-min.css">

```

我们包括 Pure.css 库，用于创建负责任的页面。

```java
<form class="pure-form pure-form-stacked" method="post" action="FileUploadServlet" 
        enctype="multipart/form-data">

```

`method`属性为 post，因为我们将数据发送到服务器。 `action`属性指定处理请求的 servlet 的名称。 `enctype`属性指定`multipart/form-data`编码类型，这是使用 HTML 格式上传文件所必需的。

```java
<input type="file" name="myfile">

```

`input`标签的`type`属性使用户可以选择一个文件。

```java
<button type="submit" class="pure-button pure-button-primary">Upload</button>

```

这是提交按钮。

在本教程中，我们展示了如何使用 Java Servlet 上传单个文件。

您可能也对以下相关教程感兴趣： [Java Servlet 分页](/articles/javaservletpagination/)， [Java Log4j 教程](/java/log4j/)， [Java Servlet RESTful 客户端](/articles/javaservletrestclient/)， [Java `RequestDispatcher`](/java/requestdispatcher/) ，[从 Java servlet](/articles/javaservlettext/) ， [Java servlet 图像教程](/articles/javaservletimage/)或 [Java 教程](/lang/java/)提供纯文本