ZetCode

Java Servlet upload file

last modified July 24, 2020

Java Servlet upload file shows how to upload a single file in a Java web application using servlet technology.

Java Servlet

Servlet is a Java class which responds to a particular type of network request - most commonly an HTTP request. Java servlets are used to create web applications. They run in servlet containers such as Tomcat or Jetty. Modern-day Java web development uses frameworks that are built on top of servlets.

HTML form encoding types

There are three encoding HTML form methods for a POST request:

The application/x-www-form-urlencoded is the default encoding. The values are encoded in key-value tuples separated by &. The = character is used between the key and the value. Non-alphanumeric characters are percent encoded. This encoding type is not suitable for binary files.

The multipart/form-data is used for non-acsii data and binary files. The input element's type attribute is set to file.

The text/plain is used for debugging.

Java Servlet upload file example

In the following application, we have a web form to select a file to be uploaded to the server. The form calls a Java servlet, which reads the file and saves it into the directory.

Upload directory

The /var/www/ directory is a standard directory for web content in Debian Linux.

$ ls -ld /var/www/upload/
drwxr-xr-x 2 www-data www-data 4096 Jul 24 11:36 /var/www/upload/

We are going to upload files to the /var/www/upload/ directory. The directory files can be modified by users who are in the www-data group. So the user who runs the web server must be in this group.

Application

This is a Maven web application; it is deployed on embedded Jetty server.

pom.xml
src
├── main
│   ├── java
│   │   └── com
│   │       └── zetcode
│   │           └── web
│   │               └── UploadFile.java
│   ├── resources
│   └── webapp
│       └── index.html
└── test
    └── java

This is the project structure.

pom.xml
<?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>

This is the Maven POM file. The javax.servlet-api artifact is for servlets.

The maven-war-plugin is responsible for collecting all artifact dependencies, classes and resources of the web application and packaging them into a web application archive (WAR). The jetty-maven-plugin is a useful Maven plugin for rapid development and testing. It creates a web application, starts a Jetty web server, and deploys the application on the server.

com/zetcode/web/UploadFile.java
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");
    }
}

The UploadFile uploads a file to the /var/www/upload/ directory.

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

With the @WebServlet annotation, we map the servlet to the /UploadFile URL pattern and define an initial uploadpath variable.

@MultipartConfig

The servlet is also decorated with @MultipartConfig. The @MultipartConfig annotation indicates that the servlet expects requests to be made using the multipart/form-data MIME type.

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

POST requests are handled by the doPost() method.

ServletOutputStream os = response.getOutputStream();

We get the servlet output stream with getOutputStream() method.

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

We retrieve the initial parameter. It is the directory where we are going to upload a file.

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

The file part is retrieved with the getPart() method.

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

We get the part's file name and input stream.

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

With Files.copy(), we copy the file to the destination directory.

os.print("File successfully uploaded");

In the end, we write a message back to the client.

webapp/index.html
<!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"
          integrity="sha384-cg6SkqEOCV1NbJoCu11+bm0NvBRc8IYLRGXkmNrqUBfTjmMYwNKPWBTIKyw9mHNJ" 
          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>

This is the home page to select a file to be uploaded. It contains an HTML form. Upon submitting the form, the processing is sent to the UploadFile.

<link rel="stylesheet" href="https://unpkg.com/purecss@2.0.3/build/pure-min.css"
        integrity="sha384-cg6SkqEOCV1NbJoCu11+bm0NvBRc8IYLRGXkmNrqUBfTjmMYwNKPWBTIKyw9mHNJ" 
        crossorigin="anonymous">

We include the Pure.css library for creating responsible pages.

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

The method attribute is post, because we send data to the server. The action attribute specifies the name of the servlet, which processes the request. The enctype attribute specifies the multipart/form-data encoding type, which is required for uploading a file with an HTML form.

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

The type attribute of the input tag lets a user choose a single file.

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

This is the Submit button.

In this tutorial, we have shown how to upload a single file with a Java servlet.

List all Java Servlet tutorials.