SpringBoot – Upload/Download MultipartFile to FileSystem – Bootstrap 4 + JQuery Ajax

In the tutorial, we guide how to build a SpringBoot web-application to Upload/Download MultipartFile to FileSystem using Bootstrap 4 & JQuery Ajax.

Technologies

  • Java 8
  • Spring Tool Suite: Version 3.9.4.RELEASE
  • Spring Boot: 2.0.2.RELEASE
  • Bootstrap 4
  • JQuery Ajax

Goal

We create a SpringBoot project as below:

SpringBoot-Upload-Download-MultipartFile-2-FileSystem-using-Bootstrap-4-JQuery-Ajax-project-structure

-> Upload/Download Form:

SpringBoot-Upload-Download-MultipartFile-2-FileSystem-using-Bootstrap-4-JQuery-Ajax-download-files

Practice

We create a SpringBoot project with below dependencies:

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

FrontEnd

Upload Multipart-Form

<!DOCTYPE html>
<html lang="en">
<head>
    <title>Upload MultipartFile</title>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
	<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.1.0/css/bootstrap.min.css">
	<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
	<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.0/umd/popper.min.js"></script>
	<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.1.0/js/bootstrap.min.js"></script>
	<script src="/js/postrequest.js"></script>
	<script src="/js/getrequest.js"></script>
</head>
 
<body>
	<div class="container h-100">
		<div class="row h-100 justify-content-center align-items-center">
			<div class="col-sm-5">
				<h3>Upload MultipartFile to FileSystem</h3>
				<form method="POST" enctype="multipart/form-data" id="fileUploadForm">
					<div class="form-group">
						<label class="control-label" for="uploadfile">Upload File:</label>
						<input type="file" class="form-control" id="uploadfile" placeholder="Upload File"  name="uploadfile"></input>
					</div>
					
			        <button type="submit" class="btn btn-default" id="btnSubmit">Upload</button>
			        <button type="button" class="btn btn-default" id="btnGetFiles">Files</button>
				</form>
				<hr/>
				<div id="listFiles">
				</div>
			</div>
		</div>
	</div>
</body>
</html>

Ajax Post/Get MultipartFile

– JQuery Ajax to Post MultipartFile is implemented in ‘\src\main\resources\static\js\postrequest.js’ file:


$(document).ready( () => {
    $("#btnSubmit").click((event) => {
        //stop submit the form, we will post it manually.
        event.preventDefault();
        doAjax();
    });
 
});
 
function doAjax() {
 
    // Get form
    var form = $('#fileUploadForm')[0];
    var data = new FormData(form);
 
    $.ajax({
        type: "POST",
        enctype: 'multipart/form-data',
        url: "/api/file/upload",
        data: data,
        processData: false, //prevent jQuery from automatically transforming the data into a query string
        contentType: false,
        cache: false,
        success: (data) => {
            $("#listFiles").text(data);
        },
        error: (e) => {
            $("#listFiles").text(e.responseText);
        }
    });
}

– JQuery Ajax to Retrieve/Download MultipartFile is implemented in ‘\src\main\resources\static\js\getrequest.js’ file:


$( document ).ready( () => {
	// GET REQUEST
	$("#btnGetFiles").click( (event) => {
		event.preventDefault();
		ajaxGet();
	});
	
	// DO GET
	function ajaxGet(){
		$.ajax({
			type : "GET",
			dataType: "json",	
			url : "/api/file/all",
			success: (data) => {
				//clear old data
				$("#listFiles").html("");
				
				/*
					render list of files
				*/
				$("#listFiles").append('
    '); $.each(data, (index, fileUrl) => { var filename = fileUrl.split('\\').pop().split('/').pop(); $("#listFiles").append('
  • ' + filename + '
  • '); }); $("#listFiles").append('
'); }, error : (err) => { $("#listFiles").html(err.responseText); } }); } })

BackEnd

File Storage

– Create interface FileStorage.java file:

 
package com.javasampleapproach.multipartfile.controller.filestorage;

import java.nio.file.Path;
import java.util.stream.Stream;

import org.springframework.core.io.Resource;
import org.springframework.web.multipart.MultipartFile;

public interface FileStorage {
	public void store(MultipartFile file);
	public Resource loadFile(String filename);
	public void deleteAll();
	public void init();
	public Stream loadFiles();
}

– Implement above interface by FileStorageImpl.java:


package com.javasampleapproach.multipartfile.controller.filestorage;

import java.io.IOException;
import java.net.MalformedURLException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.stream.Stream;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.io.Resource;
import org.springframework.core.io.UrlResource;
import org.springframework.stereotype.Service;
import org.springframework.util.FileSystemUtils;
import org.springframework.web.multipart.MultipartFile;

@Service
public class FileStorageImpl implements FileStorage{
	
	Logger log = LoggerFactory.getLogger(this.getClass().getName());
	private final Path rootLocation = Paths.get("filestorage");
 
	@Override
	public void store(MultipartFile file){
		try {
            Files.copy(file.getInputStream(), this.rootLocation.resolve(file.getOriginalFilename()));
        } catch (Exception e) {
        	throw new RuntimeException("FAIL! -> message = " + e.getMessage());
        }
	}
	
	@Override
    public Resource loadFile(String filename) {
        try {
            Path file = rootLocation.resolve(filename);
            Resource resource = new UrlResource(file.toUri());
            if(resource.exists() || resource.isReadable()) {
                return resource;
            }else{
            	throw new RuntimeException("FAIL!");
            }
        } catch (MalformedURLException e) {
        	throw new RuntimeException("Error! -> message = " + e.getMessage());
        }
    }
    
	@Override
    public void deleteAll() {
        FileSystemUtils.deleteRecursively(rootLocation.toFile());
    }

	@Override
    public void init() {
        try {
            Files.createDirectory(rootLocation);
        } catch (IOException e) {
            throw new RuntimeException("Could not initialize storage!");
        }
    }

	@Override
	public Stream loadFiles() {
        try {
            return Files.walk(this.rootLocation, 1)
                .filter(path -> !path.equals(this.rootLocation))
                .map(this.rootLocation::relativize);
        }
        catch (IOException e) {
        	throw new RuntimeException("\"Failed to read stored file");
        }
	}
}

Index Controller

– Create IndexController.java to server uploadfile.html view:

<!DOCTYPE html>
<html lang="en">
<head>
    <title>Upload MultipartFile</title>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
	<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.1.0/css/bootstrap.min.css">
	<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
	<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.0/umd/popper.min.js"></script>
	<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.1.0/js/bootstrap.min.js"></script>
	<script src="/js/postrequest.js"></script>
	<script src="/js/getrequest.js"></script>
</head>
 
<body>
	<div class="container h-100">
		<div class="row h-100 justify-content-center align-items-center">
			<div class="col-sm-5">
				<h3>Upload MultipartFile to FileSystem</h3>
				<form method="POST" enctype="multipart/form-data" id="fileUploadForm">
					<div class="form-group">
						<label class="control-label" for="uploadfile">Upload File:</label>
						<input type="file" class="form-control" id="uploadfile" placeholder="Upload File"  name="uploadfile"></input>
					</div>
					
			        <button type="submit" class="btn btn-default" id="btnSubmit">Upload</button>
			        <button type="button" class="btn btn-default" id="btnGetFiles">Files</button>
				</form>
				<hr/>
				<div id="listFiles">
				</div>
			</div>
		</div>
	</div>
</body>
</html>

Upload/Download RestAPIs

– Implement upload-file RestAPI in UploadFileController.java file:


package com.javasampleapproach.multipartfile.controller.rest;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import com.javasampleapproach.multipartfile.controller.filestorage.FileStorage;
  
@RestController
public class UploadFileController {
	 
	@Autowired 
	FileStorage fileStorage;
	
    /*
     * MultipartFile Upload
     */
    @PostMapping("/api/file/upload")
    public String uploadMultipartFile(@RequestParam("uploadfile") MultipartFile file) {
    	try {
    		fileStorage.store(file);
	    	return "File uploaded successfully! -> filename = " + file.getOriginalFilename();
		} catch (Exception e) {
			return "Error -> message = " + e.getMessage();
		}    
    }
}

– Implement download/retrieve files RestAPIs in DownloadFileController.java file:


package com.javasampleapproach.multipartfile.controller.rest;

import java.util.List;
import java.util.stream.Collectors;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.Resource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.mvc.method.annotation.MvcUriComponentsBuilder;

import com.javasampleapproach.multipartfile.controller.filestorage.FileStorage;
 
@RestController
public class DownloadFileController {
	
	@Autowired
	FileStorage fileStorage;
	
	/*
	 * List All Files
	 */
	@GetMapping("/api/file/all")
	public List getListFiles() {
		return fileStorage.loadFiles().map(
                path -> MvcUriComponentsBuilder.fromMethodName(DownloadFileController.class,
                        "downloadFile", path.getFileName().toString()).build().toString())
                .collect(Collectors.toList());
	}
	
    /*
     * Download Files
     */
	@GetMapping("/api/file/{filename}")
	public ResponseEntity downloadFile(@PathVariable String filename) {
		Resource file = fileStorage.loadFile(filename);
		return ResponseEntity.ok()
					.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + file.getFilename() + "\"")
					.body(file);	
	}
}

Run & Check Results

Run the SpringBoot project, then makes upload/download requests ->

Upload Files

SpringBoot-Upload-Download-MultipartFile-2-FileSystem-using-Bootstrap-4-JQuery-Ajax-upload-a-file

-> Stored files:

SpringBoot-Upload-Download-MultipartFile-2-FileSystem-using-Bootstrap-4-JQuery-Ajax-upload-files-to-filestorage

Retrieve Files

SpringBoot-Upload-Download-MultipartFile-2-FileSystem-using-Bootstrap-4-JQuery-Ajax-list-all-files

-> Browser Network logs:

SpringBoot-Upload-Download-MultipartFile-2-FileSystem-using-Bootstrap-4-JQuery-Ajax-list-all-files-network-logs

Download Files

SpringBoot-Upload-Download-MultipartFile-2-FileSystem-using-Bootstrap-4-JQuery-Ajax-download-files

-> Browser Network logs:

SpringBoot-Upload-Download-MultipartFile-2-FileSystem-using-Bootstrap-4-JQuery-Ajax-download-files-network-logs

SourceCode

SpringBootUploadDownloadMultipartFile



By grokonez | July 15, 2017.

Last updated on April 18, 2021.



Related Posts


Got Something To Say:

Your email address will not be published. Required fields are marked *

*