javascriptでFormDataクラスを送信するデータ群として、その一部のデータとして
Fileクラスを使うという関係の話。
FormData クラスは、HTMLフォームのデータをプログラムで簡単に構築し、
それをサーバーに送信する際に利用されます。
このクラスは、テキストフィールドやファイルなど、さまざまな種類のデータを
簡単に扱うことができます。
主なポイント
FormDataの基本FormDataクラスを使うと、key-value形式でデータを追加できます。- データは名前付きフィールドとして送信され、サーバーではフォームのように
解釈されます。
Fileクラスの使用Fileクラスは、ファイルデータを表すJavaScriptのオブジェクトです。FormDataには、appendメソッドを使ってFileオブジェクトを直接追加できます。
具体例
以下のコードは、FormDataクラスのインスタンスにテキストデータとファイルデータ
を含めて送信する例です。
javascript// フォームデータの作成
const formData = new FormData();
// テキストデータを追加
formData.append('username', 'exampleUser');
// ファイルデータを追加
const fileInput = document.querySelector('input[type="file"]');
if (fileInput.files.length > 0) {
const file = fileInput.files[0];
formData.append('profilePicture', file);
}
// サーバーに送信
fetch('/upload', {
method: 'POST',
body: formData,
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
解説
appendメソッド- 第一引数にキー名(例えば
usernameやprofilePicture)を指定します。 - 第二引数に値を指定します。値が
Fileオブジェクトの場合、そのファイルが
フォームデータとして送信されます。
- 第一引数にキー名(例えば
- ファイル選択と送信
- 上記の例では、HTMLの
<input type="file">要素を通じてファイルを
取得しています。 Fileオブジェクトは、input.files配列から取得できます。
- 上記の例では、HTMLの
fetchで送信fetchのbodyにFormDataを渡すと、ブラウザが自動的にContent-Typeをmultipart/form-dataとして設定し、境界線なども適切に処理します。
サーバー側
サーバー側では、送信されたデータを適切に解析する必要があります。
例えば、Node.jsではmulterのようなライブラリを使うことで、ファイルの処理を
簡単に行えます。
ReactとTypeScriptを使った記述
ReactとTypeScriptを使う場合、FormDataにデータを追加して送信するコードは、
型の恩恵を受けながらより堅牢に記述できます。
以下は、Reactコンポーネント内でファイルアップロードを実装する例です。
必要なポイント
- Reactの状態管理
ファイルやその他のフォームデータをuseStateで管理する。 - TypeScript型
適切な型を付けることで、コードの安全性を高める。
実装例
以下は、ファイルとテキストデータをサーバーに送信するReactコンポーネントの例です。
tsximport React, { useState, ChangeEvent, FormEvent } from 'react';
type Props = {
uploadUrl: string; // アップロード先のURLを指定
};
const FileUploadForm: React.FC<Props> = ({ uploadUrl }) => {
const [username, setUsername] = useState<string>(''); // テキストフィールド
const [file, setFile] = useState<File | null>(null); // ファイルデータ
// ユーザー名の入力ハンドラー
const handleUsernameChange = (e: ChangeEvent<HTMLInputElement>) => {
setUsername(e.target.value);
};
// ファイル選択のハンドラー
const handleFileChange = (e: ChangeEvent<HTMLInputElement>) => {
if (e.target.files && e.target.files.length > 0) {
setFile(e.target.files[0]);
}
};
// フォーム送信ハンドラー
const handleSubmit = async (e: FormEvent<HTMLFormElement>) => {
e.preventDefault();
if (!file) {
alert('ファイルを選択してください。');
return;
}
// FormDataを作成
const formData = new FormData();
formData.append('username', username);
formData.append('profilePicture', file);
try {
const response = await fetch(uploadUrl, {
method: 'POST',
body: formData,
});
if (!response.ok) {
throw new Error('アップロードに失敗しました。');
}
const result = await response.json();
console.log('アップロード成功:', result);
} catch (error) {
console.error('アップロードエラー:', error);
}
};
return (
<form onSubmit={handleSubmit}>
<div>
<label htmlFor="username">ユーザー名:</label>
<input
type="text"
id="username"
value={username}
onChange={handleUsernameChange}
/>
</div>
<div>
<label htmlFor="file">プロフィール画像:</label>
<input
type="file"
id="file"
accept="image/*"
onChange={handleFileChange}
/>
</div>
<button type="submit">アップロード</button>
</form>
);
};
export default FileUploadForm;
解説
- 状態管理
useStateを使い、フォームフィールド(username)や
ファイルデータ(file)を管理します。- ファイル選択は
File | null型で扱うのが安全です。
- 型の活用
- 入力イベントの型付けには
ChangeEventを使います。 - フォーム送信イベントには
FormEvent<HTMLFormElement>を使用します。
- 入力イベントの型付けには
FormDataとfetchFormDataでデータを構築し、fetchを用いて送信します。- サーバーへのリクエストが成功した場合と失敗した場合に分けて
エラーハンドリングを行います。
- ユーザーエクスペリエンス
- ファイルが未選択の場合に警告を表示することで、より良いUXを提供します。
サーバー側の例
Laravelを使用したサーバー側の実装方法を紹介します。
React + TypeScriptで送信されたFormDataを受け取り、ファイルを処理しつつ
その他のデータも適切に保存します。
Laravelでのセットアップ
以下の手順で、Reactから送信されたデータを処理します。
1. ルート定義
routes/web.phpまたはroutes/api.phpにルートを追加します。
phpuse App\Http\Controllers\FileUploadController;
Route::post('/upload', [FileUploadController::class, 'upload']);
2. コントローラーの作成
FileUploadControllerを作成して、データを処理します。
bashphp artisan make:controller FileUploadController
3. コントローラー実装
以下はFileUploadControllerの例です。
php<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Storage;
class FileUploadController extends Controller
{
public function upload(Request $request)
{
// バリデーション
$validated = $request->validate([
'username' => 'required|string|max:255',
'profilePicture' => 'required|file|image|max:2048', // 2MB以下の画像ファイル
]);
// ファイルの保存
if ($request->hasFile('profilePicture')) {
$file = $request->file('profilePicture');
$path = $file->store('profile_pictures', 'public'); // storage/app/public/profile_picturesに保存
// 成功時のレスポンス
return response()->json([
'message' => 'アップロード成功',
'username' => $validated['username'],
'filePath' => asset("storage/$path"), // 公開URL
], 200);
}
// エラーレスポンス
return response()->json([
'message' => 'ファイルが見つかりません。',
], 400);
}
}
4. ストレージの設定
アップロードファイルを保存するために、Laravelのstorageディレクトリを公開します。
bashphp artisan storage:link
これにより、storage/app/publicがpublic/storageにリンクされ、
ブラウザからアクセス可能になります。
5. CORS設定
Reactアプリが異なるドメイン(例: localhost:3000)で動作している場合、
CORSの設定が必要です。app/Http/Middleware/VerifyCsrfToken.phpを確認して以下を追加します。
phpprotected $except = [
'upload', // このエンドポイントではCSRFチェックを無効化
];
また、config/cors.phpで適切に設定を変更します。
(デフォルトでは全てを受け入れています。)
php'paths' => ['api/*', 'upload'],
'allowed_methods' => ['*'],
'allowed_origins' => ['http://localhost:3000'], // ReactアプリのURL
'allowed_headers' => ['*'],
'exposed_headers' => [],
'max_age' => 0,
'supports_credentials' => false,
Reactから送信されたデータの保存
React側で送信されたusernameとprofilePictureは、LaravelのRequestを通じて取得できます。
username:$request->input('username')profilePicture:$request->file('profilePicture')
ファイルは$file->store()を使って適切なパスに保存され、レスポンスとして
ファイルのURLやその他の情報を返します。
送信後のレスポンス例
成功時:
json{
"message": "アップロード成功",
"username": "exampleUser",
"filePath": "http://localhost/storage/profile_pictures/example.jpg"
}
エラー時:
json{
"message": "ファイルが見つかりません。"
}
送信後のレスポンスですが、ブラウザで確認できます。
Chromeならば、デバック画面(F12)の”ネットワーク”を表示させた状態で、
通信動作を行えば、受信内容が表示されます。
通信が行われなければ、表示はされませんので、注意が必要です。
動作確認
- フロントエンド: Reactアプリから正しいデータを送信。
- バックエンド: Laravelがデータを受け取り、ファイルを保存。
- ストレージリンク: 保存されたファイルにアクセスできることを確認。
この方法で、React + TypeScriptとLaravelを組み合わせた
ファイルアップロードシステムを構築できます。
この実装で、ReactとTypeScriptの型安全性を利用しながら、柔軟で使いやすい
ファイルアップロード機能を作成できます。
まとめ
FormDataは、Fileクラスを含むさまざまなデータを柔軟に扱える強力なツールです。
これにより、フォームの送信をプログラム的に実現できます。


