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();
}
}
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
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];
}
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"
}
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) {
...
}
...