nuxt3(h3の関数)でのファイルアップロード

NuxtJS
この記事は約4分で読めます。

花粉症に悩まされる時期がまだまだ続いておりますが、強力な薬を服用することで凌いでます。

さて、今回は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するサンプルとしています。

<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オブジェクトを渡すとパースした結果が返ります。

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のようにファイルデータをディスクに保存したりといった他の付加機能はないので、そこは自分で実装する必要があります。

参考リンク

コメント

タイトルとURLをコピーしました