DEV Community

Masui Masanori
Masui Masanori

Posted on • Edited on

3

[Micronaut] Receiving multipart/form-data

Intro

This time, I will try receiving files as "multipart/form-data".
As same as last time, I will use Undertow as a web server.

Receiving files

When using Undertow, I can't receive files using "io.micronaut.http.server.multipart.MultipartBody" as I wrote last time.

So I will use "@Part" annotations in this time.

FileController.java

package jp.masanori;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import io.micronaut.http.HttpHeaders;
import io.micronaut.http.MediaType;
import io.micronaut.http.annotation.Controller;
import io.micronaut.http.annotation.Part;
import io.micronaut.http.annotation.Post;
import io.micronaut.http.multipart.CompletedFileUpload;

@Controller("/files")
public class FileController {
    private final Logger logger;
    public FileController() {
        this.logger = LoggerFactory.getLogger(FileController.class);
    }
    @Post(uri="/sample", consumes = MediaType.MULTIPART_FORM_DATA, produces = MediaType.TEXT_PLAIN)
    public String uploadSampleFiles(HttpHeaders headers, @Part("file1") CompletedFileUpload file1) {
        logger.info("FileName: " + file1.getFilename() + " size: " + file1.getSize());
        return file1.getFilename();
    }
}
Enter fullscreen mode Exit fullscreen mode

To use the "@Part" annotation, I have to set "micronaut.server.multipart" enabled.

application.yml

micronaut:
    application:
        name: micronaut-web-app
    router:
        static-resources:
            default:
                enabled: true
                paths: classpath:static
    server:
        port: 8086
        multipart:
            # add this line
            enabled: true

            max-file-size: 20971520
Enter fullscreen mode Exit fullscreen mode

index.page.ts

window.Page = {
    send() {
        const file1Input = document.getElementById("upload_file_1") as HTMLInputElement;
        const file1 = getFile(file1Input.files);        
        const form = new FormData();
        // Must set "file1" even if there is no data 
        if(file1 == null) {
            form.append("file1", new Blob());
        } else {
            form.append("file1", file1);
        }       
        fetch("http://sample.masanori.jp:8086/files/sample", {
            method: "POST",
            mode: "cors",
            body: form
        }).then((res) => res.text())
        .then((res) => console.log(res))
        .catch(err => console.error(err));
    }
}
function getFile(files: FileList|null): File|null {
    if(files == null) {
        return null;
    }
    if(files.length <= 0 || files[0] == null) {
        return null;
    }
    return files[0];
}
Enter fullscreen mode Exit fullscreen mode

If the form data does't have the "file1" parameter, a "Bad Request" error will occur.

{
    "_links":{
        "self":[{"href":"/files/sample","templated":false}]},
        "_embedded":{"errors":[{
            "message":"Required Part [file1] not specified","path":"/file1"
            }]},
        "message":"Bad Request"
}
Enter fullscreen mode Exit fullscreen mode

I can receive two or more files like below.

FileController.java

...
@Post(uri="/sample", consumes = MediaType.MULTIPART_FORM_DATA, produces = MediaType.TEXT_PLAIN)
    public String uploadSampleFiles(HttpHeaders headers, @Part("file1") CompletedFileUpload file1,
    @Part("file2") CompletedFileUpload file2) {
...
    }
...
Enter fullscreen mode Exit fullscreen mode

Top comments (0)

Postmark Image

Speedy emails, satisfied customers

Are delayed transactional emails costing you user satisfaction? Postmark delivers your emails almost instantly, keeping your customers happy and connected.

Sign up