Spring Boot upload file

Spring Boot upload file tutorial shows how to upload a single file with Spring Boot framework.

Spring is a popular Java application framework and Spring Boot is an evolution of Spring which helps create stand-alone, production-grade Spring based applications easily.

HTML form encoding types

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

The application/x-www-form-urlencoded is the default encoding, where 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.

Spring upload file example

In the following example we have a web form to select a file to be uploaded to the server. The file is uploaded to the /var/www/upload directory.

Upload directory

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

$ ls -ld /var/www/upload/
drwxrwxr-x 2 www-data www-data 4096 Dec  3 14:29 /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

The following are the sources of the Spring Boot web application.

$ tree
.
├── pom.xml
└── src
    ├── main
    │   ├── java
    │   │   └── com
    │   │       └── zetcode
    │   │           └── web
    │   │               ├── Application.java
    │   │               └── MyController.java
    │   └── resources
    │       ├── application.properties
    │       └── static
    │           ├── failure.html
    │           ├── index.html
    │           └── success.html
    └── test
        └── java

This is the project structure of the Spring application.

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>SpringBootUploadFile</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>
    
    <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>
    
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.9.RELEASE</version>
    </parent>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>    
</project>

This is the Maven pom.xml file.

MyController.java
package com.zetcode.web;

import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;

@Controller
public class MyController {

    @Value("${upload.path}")
    private String path;

    @RequestMapping(value = "/doUpload", method = RequestMethod.POST)
    public String upload(@RequestParam MultipartFile file) throws IOException {

        if (!file.isEmpty()) {

            String fileName = file.getOriginalFilename();
            InputStream is = file.getInputStream();

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

            return "redirect:/success.html";

        } else {

            return "redirect:/failure.html";
        }
    }
}

The MyController reads the file from the request and saves it into the chosen directory.

@Value("${upload.path}")
private String path;

We read the upload directory from the application.properties file using the @Value annotation.

@RequestMapping(value = "/doUpload", method = RequestMethod.POST)
public String upload(@RequestParam MultipartFile file) throws IOException {

The upload() method is mapped to the doUpload URL pattern. Since we are sending data to the server, we use the POST request. The request parameter has the MultipartFile type.

if (!file.isEmpty()) {

We ensure that a file has been chosen with the isEmpty() method.

String fileName = file.getOriginalFilename();

We get the file name with the getOriginalFilename() method.

InputStream is = file.getInputStream();

We get the input stream with the getInputStream() method.

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

The file is copied to the destination directory from the input stream source with Files.copy().

return "redirect:/success.html";

We show a message upon successfull file upload.

application.properties
upload.path=/var/www/upload/

In the application.properties, we have an upload.path property that specifies the upload directory.

index.html
<!DOCTYPE html>
<html>
    <head>
        <title>Uploading file</title>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
    </head>
    <body>
        <h1>Uploading file</h1>

        <form action="/doUpload" method="post" enctype="multipart/form-data">
            <label>Enter file</label>
            <input type="file" name="file">
            <button type="submit">Upload</button>
        </form>
    </body>
</html>

This is the home page. It is a static file located in the src/main/resources/static directory. It contains a form to select a file and send it to the Spring application.

<form action="/doUpload" method="post" enctype="multipart/form-data">

We have chosen the doUpload URL pattern. A request created by this form will be processed by a Spring controller. 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="file">

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

<button type="submit">Upload</button>

Finally, this is a Submit button.

success.html
<!DOCTYPE html>
<html>
    <head>
        <title>Success</title>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
    </head>
    <body>
        <p>File successfully uploaded</p>
    </body>
</html>

The success.html is shown when the file is successfully uploaded to the server.

failure.html
<!DOCTYPE html>
<html>
    <head>
        <title>Failure</title>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
    </head>
    <body>
        <p>Failed to upload file</p>
    </body>
</html>

The failure.html is shown when the file upload failed.

Application.java
package com.zetcode;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class Application  {
    
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

This code sets up the Spring Boot application.

In this tutorial, we have learned how to upload a file in a Spring application. You might also be interested in the related tutorials: Spring Boot @ExceptionHandler tutorial, Spring Boot @PathVariable tutorial, Spring Boot @RequestParam tutorial, Spring Boot REST H2 tutorial, Standalone Spring applications, Java tutorial.