Let’s Develop File Upload Service From Scratch Using Java and Spring Boot
Tags: javascript, java
Published: 2021-01-13 12:17:46

We will develop a file upload service, which will be used for image upload in our e-Commerce App using Java Spring Boot

![Image for post](https://miro.medium.com/max/6000/0*Qsl7DJWEyjGfTeGg)

Photo by [Drew Coffman](https://unsplash.com/@drewcoffman?utm_source=medium&utm_medium=referral) on [Unsplash](https://unsplash.com?utm_source=medium&utm_medium=referral)

We needed an image upload functionality for our E-Commerce App, as we need to upload images for products and categories. We will build this function as a standalone service, which can be reused later. You can use this source code for uploading and displaying images for any of your products.

First, we will build the backend in [Java](/javarevisited/5-essential-frameworks-every-java-developer-should-learn-6ed83315f1fb) and [Spring](/javarevisited/10-best-online-courses-to-learn-spring-framework-in-2020-f7f73599c2fd), then integrate it with a Web client and Android Client in other tutorials

Backend Demo
============

You can test the file upload demo [**here**](http://remotedevs.org:8080/api/swagger-ui.html#/file-upload-controller)

Find the complete code [here](https://bitbucket.org/ecommerce-webtutsplus/ecommerce/src/master/src/main/java/com/webtutsplus/ecommerce/controller/FileUploadController.java)

**Backend Design**
==================

We will have 3 APIs  
1\. Upload image  
2\. Get an image by its name  
3\. Get all images

Let’s have a look at `FileUploadController` Java class which describe above 3 APIs
```
package com.webtutsplus.ecommerce.controller;

import com.webtutsplus.ecommerce.model.FileInfo;
import com.webtutsplus.ecommerce.service.FIleStoreService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.Resource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.mvc.method.annotation.MvcUriComponentsBuilder;

import java.io.IOException;
import java.nio.file.Path;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

@RestController
@RequestMapping("/fileUpload")
public class FileUploadController {

    @Autowired
    FIleStoreService fileStoreService;

    //upload a file
    @PostMapping("/")
    public String handleFileUpload(@RequestParam("file") MultipartFile file) {
        return fileStoreService.store(file);
    }


    // get all the files
    @GetMapping("/")
    public ResponseEntity<List<FileInfo>> getListFiles() {
        
        // first get a stream of all file path present in root file directory
        Stream<Path> pathStream =  fileStoreService.loadAll();
        
        List<FileInfo> fileInfos = pathStream.map(path -> {
            // get file name
            String filename = path.getFileName().toString();
            
            // use function to get one file to build the URL 
            String url = MvcUriComponentsBuilder
                    .fromMethodName(FileUploadController.class, "getFile", path.getFileName().toString()).build().toString();
            // make a fileinfo object  from filename and url 
            return new FileInfo(filename, url);
            
        }).collect(Collectors.toList());
        
        return ResponseEntity.status(HttpStatus.OK).body(fileInfos);
    }

    // get file by filename
    @GetMapping("/files/{filename:.+}")
    public ResponseEntity<Resource> getFile(@PathVariable String filename) {
        Resource file = fileStoreService.load(filename);
        return ResponseEntity.ok()
                .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + file.getFilename() + "\"").body(file);
    }

}
```

which calls the `FileStoreService` which also contains 3 methods for each APIs respectively. I have added plenty of comments to the code. Please comment below if anything is not clear.
```
package com.webtutsplus.ecommerce.service;

import com.webtutsplus.ecommerce.constants.Constants;
import com.webtutsplus.ecommerce.exceptions.StorageException;
import org.apache.commons.io.FilenameUtils;
import org.springframework.core.io.Resource;
import org.springframework.core.io.UrlResource;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.support.ServletUriComponentsBuilder;

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

@Service
public class FIleStoreService {

    Path rootLocation = Paths.get(Constants.UPLOAD_FILE_DIR);

    public String store(MultipartFile file) {
        try {
            if (file.isEmpty()) {
                throw new StorageException("Failed to store empty file.");
            }
            // find extension of the file,png or jpg
            String extension = FilenameUtils.getExtension(file.getOriginalFilename());

            // generate a random unique name for the image
            String uploadedFileName = UUID.randomUUID().toString() + "." + extension;

            // create a path for destination file
            Path destinationFile = rootLocation.resolve(Paths.get(uploadedFileName))
                                   .normalize().toAbsolutePath();

            // Copy input file to destination file path
            try (InputStream inputStream = file.getInputStream()) {
                Files.copy(inputStream, destinationFile,
                        StandardCopyOption.REPLACE_EXISTING);

                final String baseUrl =
                        ServletUriComponentsBuilder.fromCurrentContextPath().build().toUriString();

                //create the public Image URl where we can find the image
                final StringBuilder imageStringBuilder = new StringBuilder(baseUrl);
                imageStringBuilder.append("/fileUpload/files/");
                imageStringBuilder.append(uploadedFileName);

                return imageStringBuilder.toString();
            }
        }
        catch (IOException e) {
            throw new StorageException("Failed to store file.", e);
        }
    }

    public Stream<Path> loadAll() {
        // load all the files
        try {
            return Files.walk(this.rootLocation, 1)
                    // ignore the root path
                    .filter(path -> !path.equals(this.rootLocation))
                    .map(this.rootLocation::relativize);
        }
        catch (IOException e) {
            throw new StorageException("Failed to read stored files", e);
        }

    }

    public Resource load(String filename) {
        try {
            // read the file based on the filename
            Path file = rootLocation.resolve(filename);
            // get resource from path
            Resource resource = new UrlResource(file.toUri());

            if (resource.exists() || resource.isReadable()) {
                return resource;
            } else {
                throw new RuntimeException("Could not read the file!");
            }
        } catch (MalformedURLException e) {
            throw new RuntimeException("Error: " + e.getMessage());
        }
    }
}
```

That’s it, files will be now renamed with a unique name saved into `**_UPLOAD_FILE_DIR_**` directory**_._**

[

![Image for post](https://miro.medium.com/max/60/1*UDfmuQ3Ls19kmLwZY_dSSA.png?q=20)

![Image for post](https://miro.medium.com/max/5700/1*UDfmuQ3Ls19kmLwZY_dSSA.png)


Upload a file

**Get all the files**
=====================

![Image for post](https://miro.medium.com/max/60/1*FotTrSa7edNr4yVEJke4Pw.png?q=20)

![Image for post](https://miro.medium.com/max/5656/1*FotTrSa7edNr4yVEJke4Pw.png)



get all the uploaded files

Download a single file by name
==============================

![Image for post](https://miro.medium.com/max/5604/1*KarGu7LxXiKtbv23_QQPug.png)


Next step
=========

We will build an [Android Application](/javarevisited/top-5-courses-to-learn-android-for-java-programmers-667e03d995b4), which will use the APIs. The final result will look something like this.

[![IMAGE ALT TEXT HERE](http://remotedevs.org:8080/api/fileUpload/files/5af783ac-0316-4a88-bfdf-0a3dc20ec7e3.png)](https://youtu.be/GQmJmjvT0j8)