花粉症に悩まされる時期がまだまだ続いておりますが、強力な薬を服用することで凌いでます。
さて、今回はnuxt3でファイルアップロードを実装する方法を見ていきます。nodejsのexpressアプリケーションでは、multerやformidableといった素晴らしいライブラリを使って簡単にアップロード処理を実装することができます。nuxt3(h3)でmulterやformidableのライブラリを使うこともできるのですが、外部ライブラリを使わずとも標準機能で簡単にファイルアップロードを実装することができるようになっています。今回はその方法を見ていきます。
環境
- macOS Catalina (intel cpu)
- nuxt 3.4.1
- Node.js 18.15.0
サンプル
早速サンプルを見ていきます。
app.vue
fetch
でformデータを処理するにはFormData
を使います。今回は、textとfileの2種類のデータをPOSTするサンプルとしています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
<script setup lang="ts"> const files = ref<FileList>(); const title = ref(""); const uploadData = ref(); function changeFiles(event: Event) { const result = event!.target as HTMLInputElement; files.value = result.files!; } async function upload() { const formData = new FormData(); formData.append("title", title.value); if (files.value) { for (const item of files.value!) { formData.append("files", item, encodeURIComponent(item.name)); // 日本語ファイル名はエンコード } } await useFetch("/api/upload", { method: "POST", body: formData, }).then((result) => { uploadData.value = result.data; }); } </script> <template> <div> <h2>File Uploads</h2> <form @submit.prevent="upload"> <div>Text field title: <input type="text" name="title" /></div> <div> File: <input type="file" name="files" @change="changeFiles" multiple /> </div> <input type="submit" value="アップロード" /> </form> {{ uploadData }} </div> </template> |
server/api/upload.post.ts
readMultipartFormData
という関数でbodyをパースします。この関数は、nuxt3の内部で使われているh3というフレームワークが提供している関数です。関数の引数にevent
オブジェクトを渡すとパースした結果が返ります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
export default defineEventHandler(async (event) => { const files = await readMultipartFormData(event); if (!files || files.length === 0) { throw createError({ statusCode: 400, statusMessage: "No files were uploaded", }); } const uploaded = files.map((item) => ({ contentType: item.type, filename: decodeURIComponent(item.filename!), // エンコードしているのでデコード name: item.name, size: item.data.length, })); return { uploaded }; }); |
早速実行してみましょう。3つの日本語ファイル名を含む画像ファイルを送信してみます。
リクエストした結果を返せていることが分かります。
まとめ
nuxt3では、標準でファイルアップロードを実装するための関数があります。multerやformidableのようにファイルデータをディスクに保存したりといった他の付加機能はないので、そこは自分で実装する必要があります。
参考リンク
- https://github.com/unjs/h3
- https://github.com/unjs/h3/blob/main/src/utils/internal/multipart.ts
- https://github.com/node-formidable/formidable
- https://github.com/expressjs/multer
コメント