【Spring Boot】Uploaded Image Processing

example

import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.UUID;

@RestController
@RequestMapping("/api/users")
public class UserController {

    private static final String AVATAR_UPLOAD_DIR = "uploads/avatars/";

    @PostMapping("/register")
    public ResponseEntity<String> registerUser(
            @RequestPart("userInfo") UserRegistrationDto userInfo,
            @RequestParam(value = "avatar", required = false) MultipartFile avatarFile) {
        
        // Generate a unique user ID
        String userId = UUID.randomUUID().toString();

        // Process user information
        System.out.println("Registering user: " + userInfo.getUsername());
        System.out.println("Email: " + userInfo.getEmail());
        // Here you would typically save the user information to a database

        // Process avatar if provided
        String avatarUrl = null;
        if (avatarFile != null && !avatarFile.isEmpty()) {
            avatarUrl = saveAvatar(avatarFile, userId);
        }

        // Construct response
        String response = "User registered successfully. " +
                "Username: " + userInfo.getUsername() +
                ", Email: " + userInfo.getEmail();
        if (avatarUrl != null) {
            response += ", Avatar URL: " + avatarUrl;
        }

        return ResponseEntity.ok(response);
    }

    private String saveAvatar(MultipartFile file, String userId) {
        try {
            String fileName = userId + "_" + file.getOriginalFilename();
            Path path = Paths.get(AVATAR_UPLOAD_DIR + fileName);
            Files.write(path, file.getBytes());
            return "/avatars/" + fileName; // Return the relative URL
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }
}

class UserRegistrationDto {
    private String username;
    private String email;
    private String password; // Note: In a real application, never store passwords in plain text

    // Getters and setters
}

We use @RequestPart for userInfo because it’s a complex object (JSON data) that needs to be deserialized into a UserRegistrationDto object. We use @RequestParam for avatarFile because it’s a simple file upload. While we could use @RequestPart here as well, @RequestParam is sufficient and clearly indicates that it’s an optional parameter.

@RequestPart

@RequestParam

Typically used for simple values like strings, numbers, or booleans. By default, parameters are required. You can make them optional by setting required = false.

  • For GET requests, it looks at query parameters.
  • For requests with application/x-www-form-urlencoded, it looks at the form data in the request body.
  • For requests with multipart/form-data, it can look at both the URL and the parts of the multipart request.
  • It can even extract data from the query string for POST requests, which is occasionally useful.

compare with @PathVariable

@PathVariable

  • Used to handle template variables in the request URI.
  • Part of the path itself, not a query string.
  • Typically used for mandatory parameters that identify a resource.
  • Cannot have default values (if the value is not in the URL, the route won’t match).
@GetMapping("/users/{id}")
public User getUser(@PathVariable Long id) {
    // Implementation
}

@Request Body

For application/json or application/xml

application/x-www-form-urlencoded and multipart/form-data

application/x-www-form-urlencoded

This is the default content type for HTML form submissions and is widely used for sending simple data.

Key characteristics

  • Data is encoded in key-value pairs
  • Keys and values are URL-encoded (spaces become ‘+’ or ‘%20’, special characters are percent-encoded)
  • Pairs are separated by ‘&

Pros

  • Simple and widely supported
  • Efficient for small amounts of text data
  • Easy to generate and parse

⠀Cons

  • Not suitable for sending large amounts of data
  • Not efficient for sending binary data (like files)
  • Can become unwieldy with complex data structures

multipart/form-data

This content type is used when the form includes files, non-ASCII data, or when you need to send binary data.

Key characteristics

  • The body is divided into separate parts, each representing a form field or file
  • Each part can have its own content type
  • Parts are separated by a boundary delimiter

example

--boundary
Content-Disposition: form-data; name="name"

John Doe
--boundary
Content-Disposition: form-data; name="file"; filename="example.txt"
Content-Type: text/plain

[File content goes here]
--boundary--

Pros

  • Can handle file uploads efficiently
  • Supports mixed data types (text fields and files) in a single request
  • Better for sending large amounts of data or binary data
  • Each part can have its own content type

⠀Cons

  • More complex to parse and generate
  • Slightly larger overhead due to boundaries and headers

Get Method

HTTP Specification

According to the HTTP/1.1 specification (RFC 7231), a GET request can have a body. However, the specification also states that a GET request with a body has no defined semantics, meaning servers are not required to process or even acknowledge the body.

Real-world Practice

In practice, while it’s technically possible to send a body with a GET request, it’s generally discouraged and often not supported for several reasons:

  • Many servers, clients, and proxies ignore the body of a GET request.
  • Some implementations might reject GET requests with a body.
  • It goes against the intended use of GET as defined in the HTTP specification.

RESTful API Design

In RESTful API design, GET requests are meant to be safe and idempotent. They should retrieve resources without modifying server state. Including a body in a GET request could imply that the request is intended to modify something, which contradicts these principles.

Licensed under CC BY-NC-SA 4.0
Last updated on Jul 13, 2024 00:00 UTC
comments powered by Disqus
Built with Hugo
Theme Stack designed by Jimmy