SvelteKitでファイルアップロード機能を実装する

2024/12/15に公開

Sveltekit を用いたプロジェクトでのファイルアップロード機能を実装します。開発中の備忘録です。

作るもの

ローカル PC に存在するファイルをサーバー上の任意のフォルダにアップロードする機能です。
またアップロード後にそのファイルなどを用いた処理を行えるようにします。

環境

事前に SvelteKit での環境は作ってある前提で話を進めます。

  • svelte : ^5.0.0
  • sveltejs/kit : ^2.9.0

コード

アップロードフォーム

src/routes/+page.svelteを編集します。特に変哲もないファイルアップロードのためのHTMLフォームですね。

multipart/form-dataでファイル送信の準備をしておきます。

src/routes/+page.svelte
<form method="post" enctype="multipart/form-data">
  <input type="file" name="file" />
  <button>Upload</button>
</form>

アップロード処理

src/routes/+page.server.jsに以下のコードを記述します。
+page.server.jsファイルはactionsをエクスポートするためです。

src/routes/+page.server.js
import { writeFile } from 'fs/promises';
import { Buffer } from 'buffer';
import path from 'path';

/** @type {import('./$types').Actions} */
export const actions = {
  default: async ({ request }) => {
    try{
      const formData = await request.formData();
      const file = formData.get('file');
      const fileName = `${randomUUID()}${path.extname(file.name)}`;
      const filePath = `./static/uploads/${fileName}`;
      await writeFile(filePath, Buffer.from(await file.arrayBuffer()));

      return { success: true, fileName: fileName };
    } catch (e){
      // エラー時の処理を記述
      return { success: false }
    }
  }
};

actionオブジェクトにはdefaultプロパティを置き、フォームが送信されたときに実行される非同期関数を記述します。

formData()でアップロードされたファイル情報を準備し、fileにローカルからアップロードされたファイル情報を格納します。

.get('file')'file'はフロントエンド側のフォーム入力部分の名前です。

ファイルネームは適当に決めちゃってください。path.extnameでアップロードされたファイルの拡張子を取得しています。

サーバーへのアップロードにはwriteFileを用いて行います。writeFileではファイル情報をBuffer等で指定することが求められているのでそれに従います。

アップロードに成功したら、成功した旨を伝える情報とファイル名を返します。これでファイルのアップロード自体は終了しました。

成功を受け取る

成功したことをフロントエンド側で受け取ります。
フロントエンドで情報を受け取ることでページ遷移等なしで、次の処理(アップロードファイルの表示とか?)を行うことができます。

src/routes/+page.svelteに以下の記述を追加します。

src/routes/+page.svelte
<script>
  export let form;
</script>

<!-- さっきのフォームのコード -->

{#if form?.success}
  <!-- ここに成功時の処理を記述 -->
  <p>ファイル名:{form.fileName}</p>
{:else}
  <!-- ここに失敗時の処理を記述 -->
  <p>エラーです!</p>
{/if}

( .svelteのシンタックスハイライト対応してなくて悲しい )

export let form+page.server.jsでの返り値を取得します。
下部で返り値の情報により条件分岐させ、その後の処理を指定することができます。

おーわり!

https://kit.svelte.jp/docs/form-actions

https://nodejs.org/api/fs.html#fspromiseswritefilefile-data-options

https://travishorn.com/uploading-and-saving-files-with-sveltekit

https://azukiazusa.dev/blog/sveltekit-form-action/

Discussion