Spring – How to store uploaded file on the server

A common task that might pop-up (hopefully just once and then abstract) in the life of a software engineer is to handle a file upload from the client and store it in a folder on the server machine.

 

If you are using Spring that can be done really easy, even easier if you are willing to add some third party libraries in your project that would make writing the file on the server easier and more terse.

Let’s check our Controller, or in other words, the method that is called when a request comes to the server for specific URL + HTTP METHOD combination.

@RequestMapping(
    path = "/process",
    method = RequestMethod.POST,
    consumes={"multipart/form-data"},
    produces= {"application/zip"}
)
public FileSystemResource process(@RequestParam("file_upload") MultipartFile file, HttpServletResponse response) {

The important parts here are the “consumes” property. The value is a specific Mime Type which is a great format for uploading files or binary data. Which basically means “Hey, I eat only sliced bread”. This format specifies a boundary, or a term that is more familiar, a separator for each of the fields in the form, so we get something like a map at the end and we need to get the file. The way that we tell Spring that we want a specific value from this map is with the @RequestParam annotation.

Where this map comes from originally?

On the client we construct it. For that, we use the FormData class.

An example of a function that encodes an uploaded file (that which comes from the input with type=””file”) to FormData:

public fileToObjectData(file: File) {
  let formData: FormData = new FormData();

  formData.append('file_upload', file, file.name);

  return formData;
}

We use the key “file_upload” so at the other end, on the server we use the same key to fetch the File (not really a file, as you will learn soon…)

As we can see from above, the type of the file is MultipartFile. In order to save it on the file system we need to convert it to the Java’s File class.

public File convert(MultipartFile multipartFile) throws IOException { 
  File convFile = new File(buildFilePathName(multipartFile));
  convFile.createNewFile(); 
  FileOutputStream fos = new FileOutputStream(convFile); 
  fos.write(multipartFile.getBytes());
  fos.close(); 
  return convFile;
}

Let’s go through the lines one by one.

1. A “magic” method that takes the filename and appends in on the output folder path to create File’s path.
2. We create empty file on the file system, only if it does not exist yet.
3. Create a FileOutputStream in order to write to the file we created.
4. Write the byte data from the MultipartFile instance.
5. Closing the resource so it’s free to use by other threads and to free the references.
6. You know that one…

And that’s it!