Languages
[Edit]
EN

Spring Boot 3 - optimal way to send JSON data with binary files in request

6 points
Created by:
Creg
9600

In this article, we would like to show how to optimal way to make POST request with JSON data and binary files in Spring Boot 3.

The JSON format does not allow direct transmission of binary files.

There are available solutions:

  • quite optimal: encode binary files using Base94 (as improvement to Base64) and send them inside JSONs,
  • super optimal: use multipart/form-data as Content-Type and send JSON and binary files inside parts.

The article presents multipart/form-data approach.

Example project

In the project JSON part has name json and names of file parts use file-* pattern.

The project structure

Example project to upload binary files with JSON data using Spring Boot 3.
Example project to upload binary files with JSON data using Spring Boot 3.

 

The project files

src/main/resources/application.properties file:

spring.application.name=demo

spring.servlet.multipart.max-file-size=10MB
spring.servlet.multipart.max-request-size=10MB

 

src/main/resources/static/index.html file:

<!doctype html>
<html>
<body>
  <script>

    const ENCODER = new TextEncoder();  // it uses UTF-8

    // Source: https://dirask.com/snippets/JavaScript-convert-object-to-Blob-application-json-charset-UTF-8-DZNVXD
    //
    const createBlob = (object) => {
        const json = JSON.stringify(object);
        const parts = [
            ENCODER.encode(json)
        ];
        const options = {
            type: 'application/json;charset=UTF-8'
        };
        return new Blob(parts, options);
    };

    const sendPost = async (url, data) => {
        const response = await fetch(url, {
            method: 'POST',
            body: data
        });
        return await response.json();
    };

    const handleSubmit = async (event) => {
        const elements = event.elements;
        const jsonData = {
            property1: 'value-1',
            property2: 'value-2',
            property3: 'value-3',
            // Put more properties here ...
        };
        const file1Element = elements.namedItem('file-1');  // <input type="file" name="file-1" />
        const file2Element = elements.namedItem('file-2');  // <input type="file" name="file-2" />
        const file3Element = elements.namedItem('file-3');  // <input type="file" name="file-3" />
        // Put more files here ...
        const formData = new FormData();
        formData.append('json', createBlob(jsonData));
        formData.append('file-1', file1Element.files[0]);
        formData.append('file-2', file2Element.files[0]);
        formData.append('file-3', file3Element.files[0]);
        // Put more files here ...
        return await sendPost('/api/backend', formData);
    };
    
  </script>
  <form action="javascript: void 0;" onsubmit="handleSubmit(this)">
    File 1: <input type="file" name="file-1" /><br />
    File 2: <input type="file" name="file-2" /><br />
    File 3: <input type="file" name="file-3" /><br />
            <!-- Put more files here ...   -->
    <button type="submit">Send</button>
 </form>
</body>
</html>

Hint: to distinguish what file is related with what part in JSON data, we can put file names inside JSON data.

 

src/main/java/com/example/demo/UploadController.java file:

package com.example.demo;

import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestPart;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;

import com.example.demo.requests.JsonRequest;
import com.example.demo.responses.UploadResponse;

@Controller
public class UploadController {

    @PostMapping(
        value = "/api/backend",
        consumes = MediaType.MULTIPART_FORM_DATA_VALUE,
        produces = MediaType.APPLICATION_JSON_VALUE
    )
    @ResponseBody
    public UploadResponse handleForm(
        @RequestPart("json") JsonRequest jsonRequest,
        @RequestPart("file-1") MultipartFile requestFile1,
        @RequestPart("file-2") MultipartFile requestFile2,
        @RequestPart("file-3") MultipartFile requestFile3
        // Put more files here ...
    ) {
        // ...

        return new UploadResponse(true);
    }
}

 

src/main/java/com/example/demo/DemoApplication.java file:

package com.example.demo;

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

@SpringBootApplication
public class DemoApplication {

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

 

src/main/java/com/example/demo/requests/JsonRequest.java file:

package com.example.demo.requests;

import lombok.Getter;
import lombok.Setter;
import lombok.NoArgsConstructor;
import lombok.AllArgsConstructor;

@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class JsonRequest {
    String property1;
    String property2;
    String property3;
    // Put more properties here ...
}

 

src/main/java/com/example/demo/responses/UploadResponse.java file:

package com.example.demo.responses;

import lombok.Getter;
import lombok.Setter;
import lombok.NoArgsConstructor;
import lombok.AllArgsConstructor;

@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class UploadResponse {
    boolean result;
}

 

pom.xml file:

<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">

	<modelVersion>4.0.0</modelVersion>

	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>3.3.4</version>
		<relativePath/>
	</parent>

	<groupId>com.example</groupId>
	<artifactId>demo</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>demo</name>
	<description>Spring Boot - demo project</description>
	
	<properties>
		<java.version>17</java.version>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
			<optional>true</optional>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
				<configuration>
					<excludes>
						<exclude>
							<groupId>org.projectlombok</groupId>
							<artifactId>lombok</artifactId>
						</exclude>
					</excludes>
				</configuration>
			</plugin>
		</plugins>
	</build>

</project>

 

The final effect

Run the application and open http://localhost:8080 to see the effect.

Example application to upload binary files with JSON data in Spring Boot 3.
Example application to upload binary files with JSON data in Spring Boot 3.

 

Alternative titles

  1. Spring Boot 3 - optimal way to upload binary files with JSON data
  2. Spring Boot 3 - optimal way to make POST request with JSON data and binary files
  3. Spring Boot 3 - send JSON data and files as multipart
Donate to Dirask
Our content is created by volunteers - like Wikipedia. If you think, the things we do are good, donate us. Thanks!
Join to our subscribers to be up to date with content, news and offers.
Native Advertising
🚀
Get your tech brand or product in front of software developers.
For more information Contact us
Dirask - we help you to
solve coding problems.
Ask question.

❤️💻 🙂

Join