[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

<span>package</span> <span>jp.masanori</span><span>;</span>
<span>import</span> <span>org.slf4j.Logger</span><span>;</span>
<span>import</span> <span>org.slf4j.LoggerFactory</span><span>;</span>
<span>import</span> <span>io.micronaut.http.HttpHeaders</span><span>;</span>
<span>import</span> <span>io.micronaut.http.MediaType</span><span>;</span>
<span>import</span> <span>io.micronaut.http.annotation.Controller</span><span>;</span>
<span>import</span> <span>io.micronaut.http.annotation.Part</span><span>;</span>
<span>import</span> <span>io.micronaut.http.annotation.Post</span><span>;</span>
<span>import</span> <span>io.micronaut.http.multipart.CompletedFileUpload</span><span>;</span>
<span>@Controller</span><span>(</span><span>"/files"</span><span>)</span>
<span>public</span> <span>class</span> <span>FileController</span> <span>{</span>
<span>private</span> <span>final</span> <span>Logger</span> <span>logger</span><span>;</span>
<span>public</span> <span>FileController</span><span>()</span> <span>{</span>
<span>this</span><span>.</span><span>logger</span> <span>=</span> <span>LoggerFactory</span><span>.</span><span>getLogger</span><span>(</span><span>FileController</span><span>.</span><span>class</span><span>);</span>
<span>}</span>
<span>@Post</span><span>(</span><span>uri</span><span>=</span><span>"/sample"</span><span>,</span> <span>consumes</span> <span>=</span> <span>MediaType</span><span>.</span><span>MULTIPART_FORM_DATA</span><span>,</span> <span>produces</span> <span>=</span> <span>MediaType</span><span>.</span><span>TEXT_PLAIN</span><span>)</span>
<span>public</span> <span>String</span> <span>uploadSampleFiles</span><span>(</span><span>HttpHeaders</span> <span>headers</span><span>,</span> <span>@Part</span><span>(</span><span>"file1"</span><span>)</span> <span>CompletedFileUpload</span> <span>file1</span><span>)</span> <span>{</span>
<span>logger</span><span>.</span><span>info</span><span>(</span><span>"FileName: "</span> <span>+</span> <span>file1</span><span>.</span><span>getFilename</span><span>()</span> <span>+</span> <span>" size: "</span> <span>+</span> <span>file1</span><span>.</span><span>getSize</span><span>());</span>
<span>return</span> <span>file1</span><span>.</span><span>getFilename</span><span>();</span>
<span>}</span>
<span>}</span>
<span>package</span> <span>jp.masanori</span><span>;</span>

<span>import</span> <span>org.slf4j.Logger</span><span>;</span>
<span>import</span> <span>org.slf4j.LoggerFactory</span><span>;</span>

<span>import</span> <span>io.micronaut.http.HttpHeaders</span><span>;</span>
<span>import</span> <span>io.micronaut.http.MediaType</span><span>;</span>
<span>import</span> <span>io.micronaut.http.annotation.Controller</span><span>;</span>
<span>import</span> <span>io.micronaut.http.annotation.Part</span><span>;</span>
<span>import</span> <span>io.micronaut.http.annotation.Post</span><span>;</span>
<span>import</span> <span>io.micronaut.http.multipart.CompletedFileUpload</span><span>;</span>

<span>@Controller</span><span>(</span><span>"/files"</span><span>)</span>
<span>public</span> <span>class</span> <span>FileController</span> <span>{</span>
    <span>private</span> <span>final</span> <span>Logger</span> <span>logger</span><span>;</span>
    <span>public</span> <span>FileController</span><span>()</span> <span>{</span>
        <span>this</span><span>.</span><span>logger</span> <span>=</span> <span>LoggerFactory</span><span>.</span><span>getLogger</span><span>(</span><span>FileController</span><span>.</span><span>class</span><span>);</span>
    <span>}</span>
    <span>@Post</span><span>(</span><span>uri</span><span>=</span><span>"/sample"</span><span>,</span> <span>consumes</span> <span>=</span> <span>MediaType</span><span>.</span><span>MULTIPART_FORM_DATA</span><span>,</span> <span>produces</span> <span>=</span> <span>MediaType</span><span>.</span><span>TEXT_PLAIN</span><span>)</span>
    <span>public</span> <span>String</span> <span>uploadSampleFiles</span><span>(</span><span>HttpHeaders</span> <span>headers</span><span>,</span> <span>@Part</span><span>(</span><span>"file1"</span><span>)</span> <span>CompletedFileUpload</span> <span>file1</span><span>)</span> <span>{</span>
        <span>logger</span><span>.</span><span>info</span><span>(</span><span>"FileName: "</span> <span>+</span> <span>file1</span><span>.</span><span>getFilename</span><span>()</span> <span>+</span> <span>" size: "</span> <span>+</span> <span>file1</span><span>.</span><span>getSize</span><span>());</span>
        <span>return</span> <span>file1</span><span>.</span><span>getFilename</span><span>();</span>
    <span>}</span>
<span>}</span>
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

<span>micronaut</span><span>:</span>
<span>application</span><span>:</span>
<span>name</span><span>:</span> <span>micronaut-web-app</span>
<span>router</span><span>:</span>
<span>static-resources</span><span>:</span>
<span>default</span><span>:</span>
<span>enabled</span><span>:</span> <span>true</span>
<span>paths</span><span>:</span> <span>classpath:static</span>
<span>server</span><span>:</span>
<span>port</span><span>:</span> <span>8086</span>
<span>multipart</span><span>:</span>
<span># add this line</span>
<span>enabled</span><span>:</span> <span>true</span>
<span>max-file-size</span><span>:</span> <span>20971520</span>
<span>micronaut</span><span>:</span>
    <span>application</span><span>:</span>
        <span>name</span><span>:</span> <span>micronaut-web-app</span>
    <span>router</span><span>:</span>
        <span>static-resources</span><span>:</span>
            <span>default</span><span>:</span>
                <span>enabled</span><span>:</span> <span>true</span>
                <span>paths</span><span>:</span> <span>classpath:static</span>
    <span>server</span><span>:</span>
        <span>port</span><span>:</span> <span>8086</span>
        <span>multipart</span><span>:</span>
            <span># add this line</span>
            <span>enabled</span><span>:</span> <span>true</span>

            <span>max-file-size</span><span>:</span> <span>20971520</span>
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

<span>window</span><span>.</span><span>Page</span> <span>=</span> <span>{</span>
<span>send</span><span>()</span> <span>{</span>
<span>const</span> <span>file1Input</span> <span>=</span> <span>document</span><span>.</span><span>getElementById</span><span>(</span><span>"</span><span>upload_file_1</span><span>"</span><span>)</span> <span>as</span> <span>HTMLInputElement</span><span>;</span>
<span>const</span> <span>file1</span> <span>=</span> <span>getFile</span><span>(</span><span>file1Input</span><span>.</span><span>files</span><span>);</span>
<span>const</span> <span>form</span> <span>=</span> <span>new</span> <span>FormData</span><span>();</span>
<span>// Must set "file1" even if there is no data </span>
<span>if</span><span>(</span><span>file1</span> <span>==</span> <span>null</span><span>)</span> <span>{</span>
<span>form</span><span>.</span><span>append</span><span>(</span><span>"</span><span>file1</span><span>"</span><span>,</span> <span>new</span> <span>Blob</span><span>());</span>
<span>}</span> <span>else</span> <span>{</span>
<span>form</span><span>.</span><span>append</span><span>(</span><span>"</span><span>file1</span><span>"</span><span>,</span> <span>file1</span><span>);</span>
<span>}</span>
<span>fetch</span><span>(</span><span>"</span><span>http://sample.masanori.jp:8086/files/sample</span><span>"</span><span>,</span> <span>{</span>
<span>method</span><span>:</span> <span>"</span><span>POST</span><span>"</span><span>,</span>
<span>mode</span><span>:</span> <span>"</span><span>cors</span><span>"</span><span>,</span>
<span>body</span><span>:</span> <span>form</span>
<span>}).</span><span>then</span><span>((</span><span>res</span><span>)</span> <span>=></span> <span>res</span><span>.</span><span>text</span><span>())</span>
<span>.</span><span>then</span><span>((</span><span>res</span><span>)</span> <span>=></span> <span>console</span><span>.</span><span>log</span><span>(</span><span>res</span><span>))</span>
<span>.</span><span>catch</span><span>(</span><span>err</span> <span>=></span> <span>console</span><span>.</span><span>error</span><span>(</span><span>err</span><span>));</span>
<span>}</span>
<span>}</span>
<span>function</span> <span>getFile</span><span>(</span><span>files</span><span>:</span> <span>FileList</span><span>|</span><span>null</span><span>):</span> <span>File</span><span>|</span><span>null</span> <span>{</span>
<span>if</span><span>(</span><span>files</span> <span>==</span> <span>null</span><span>)</span> <span>{</span>
<span>return</span> <span>null</span><span>;</span>
<span>}</span>
<span>if</span><span>(</span><span>files</span><span>.</span><span>length</span> <span><=</span> <span>0</span> <span>||</span> <span>files</span><span>[</span><span>0</span><span>]</span> <span>==</span> <span>null</span><span>)</span> <span>{</span>
<span>return</span> <span>null</span><span>;</span>
<span>}</span>
<span>return</span> <span>files</span><span>[</span><span>0</span><span>];</span>
<span>}</span>
<span>window</span><span>.</span><span>Page</span> <span>=</span> <span>{</span>
    <span>send</span><span>()</span> <span>{</span>
        <span>const</span> <span>file1Input</span> <span>=</span> <span>document</span><span>.</span><span>getElementById</span><span>(</span><span>"</span><span>upload_file_1</span><span>"</span><span>)</span> <span>as</span> <span>HTMLInputElement</span><span>;</span>
        <span>const</span> <span>file1</span> <span>=</span> <span>getFile</span><span>(</span><span>file1Input</span><span>.</span><span>files</span><span>);</span>        
        <span>const</span> <span>form</span> <span>=</span> <span>new</span> <span>FormData</span><span>();</span>
        <span>// Must set "file1" even if there is no data </span>
        <span>if</span><span>(</span><span>file1</span> <span>==</span> <span>null</span><span>)</span> <span>{</span>
            <span>form</span><span>.</span><span>append</span><span>(</span><span>"</span><span>file1</span><span>"</span><span>,</span> <span>new</span> <span>Blob</span><span>());</span>
        <span>}</span> <span>else</span> <span>{</span>
            <span>form</span><span>.</span><span>append</span><span>(</span><span>"</span><span>file1</span><span>"</span><span>,</span> <span>file1</span><span>);</span>
        <span>}</span>       
        <span>fetch</span><span>(</span><span>"</span><span>http://sample.masanori.jp:8086/files/sample</span><span>"</span><span>,</span> <span>{</span>
            <span>method</span><span>:</span> <span>"</span><span>POST</span><span>"</span><span>,</span>
            <span>mode</span><span>:</span> <span>"</span><span>cors</span><span>"</span><span>,</span>
            <span>body</span><span>:</span> <span>form</span>
        <span>}).</span><span>then</span><span>((</span><span>res</span><span>)</span> <span>=></span> <span>res</span><span>.</span><span>text</span><span>())</span>
        <span>.</span><span>then</span><span>((</span><span>res</span><span>)</span> <span>=></span> <span>console</span><span>.</span><span>log</span><span>(</span><span>res</span><span>))</span>
        <span>.</span><span>catch</span><span>(</span><span>err</span> <span>=></span> <span>console</span><span>.</span><span>error</span><span>(</span><span>err</span><span>));</span>
    <span>}</span>
<span>}</span>
<span>function</span> <span>getFile</span><span>(</span><span>files</span><span>:</span> <span>FileList</span><span>|</span><span>null</span><span>):</span> <span>File</span><span>|</span><span>null</span> <span>{</span>
    <span>if</span><span>(</span><span>files</span> <span>==</span> <span>null</span><span>)</span> <span>{</span>
        <span>return</span> <span>null</span><span>;</span>
    <span>}</span>
    <span>if</span><span>(</span><span>files</span><span>.</span><span>length</span> <span><=</span> <span>0</span> <span>||</span> <span>files</span><span>[</span><span>0</span><span>]</span> <span>==</span> <span>null</span><span>)</span> <span>{</span>
        <span>return</span> <span>null</span><span>;</span>
    <span>}</span>
    <span>return</span> <span>files</span><span>[</span><span>0</span><span>];</span>
<span>}</span>
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"
}
{
    "_links":{
        "self":[{"href":"/files/sample","templated":false}]},
        "_embedded":{"errors":[{
            "message":"Required Part [file1] not specified","path":"/file1"
            }]},
        "message":"Bad Request"
}
{ "_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

<span>...</span>
<span>@Post</span><span>(</span><span>uri</span><span>=</span><span>"/sample"</span><span>,</span> <span>consumes</span> <span>=</span> <span>MediaType</span><span>.</span><span>MULTIPART_FORM_DATA</span><span>,</span> <span>produces</span> <span>=</span> <span>MediaType</span><span>.</span><span>TEXT_PLAIN</span><span>)</span>
<span>public</span> <span>String</span> <span>uploadSampleFiles</span><span>(</span><span>HttpHeaders</span> <span>headers</span><span>,</span> <span>@Part</span><span>(</span><span>"file1"</span><span>)</span> <span>CompletedFileUpload</span> <span>file1</span><span>,</span>
<span>@Part</span><span>(</span><span>"file2"</span><span>)</span> <span>CompletedFileUpload</span> <span>file2</span><span>)</span> <span>{</span>
<span>...</span>
<span>}</span>
<span>...</span>
<span>...</span>
<span>@Post</span><span>(</span><span>uri</span><span>=</span><span>"/sample"</span><span>,</span> <span>consumes</span> <span>=</span> <span>MediaType</span><span>.</span><span>MULTIPART_FORM_DATA</span><span>,</span> <span>produces</span> <span>=</span> <span>MediaType</span><span>.</span><span>TEXT_PLAIN</span><span>)</span>
    <span>public</span> <span>String</span> <span>uploadSampleFiles</span><span>(</span><span>HttpHeaders</span> <span>headers</span><span>,</span> <span>@Part</span><span>(</span><span>"file1"</span><span>)</span> <span>CompletedFileUpload</span> <span>file1</span><span>,</span>
    <span>@Part</span><span>(</span><span>"file2"</span><span>)</span> <span>CompletedFileUpload</span> <span>file2</span><span>)</span> <span>{</span>
<span>...</span>
    <span>}</span>
<span>...</span>
... @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

原文链接:[Micronaut] Receiving multipart/form-data

© 版权声明
THE END
喜欢就支持一下吧
点赞11 分享
Every day has not danced, all are life's disappointment.
每一个不曾起舞的日子,都是对生命的辜负
评论 抢沙发

请登录后发表评论

    暂无评论内容