上記の記事では、multipart/form-data
のリクエストフォーマットとその解決策について説明しました。この記事では、実際の開発で遭遇する問題とその応用について解説します。
具体的には、次のフォームアプリケーションに関連するいくつかの部分を含みます:
<form/>
タグの背後で行われる処理- JavaScriptでのFormDataの使用
- FormDataと
fetch
の組み合わせ - JavaScriptによるファイルの操作方法
formタグについて再考する
実際には、HTMLのformタグには、開発者が見落とすことがあるブラウザによって実装された詳細がたくさんあります。以下の例を考えてみましょう:
<form method="POST" action="/upload" enctype="multipart/form-data">
<input type="text" name="name" />
<input type="file" name="file" />
<button>
Submit
</button>
</form>
JavaScriptコードがない状態で、Submitボタンをクリックすると、ブラウザが以下のことを自動的に行います:
- input内のnameとfileフィールドをシリアライズする
Content-Type: multipart/form-data
のHTTPリクエストでPOSTメソッドを送信する- ファイルを読み取り、リクエストのコンテンツに追加する(ファイルが存在する場合)
シングルページアプリケーションやフロントエンドフレームワークがまだ一般的ではなかった時代には、データを入力してフォームを送信し、他のページにリダイレクトするという方法が一般的でした。しかし、入力するデータが増えたり、一部の領域のみを更新する必要がある場合(コメントなど)、ユーザーにとってはページ全体を更新する必要があるため、ユーザーエクスペリエンスは良くありませんでした。そのため、Ajaxを使用してAPIを呼び出し、JavaScriptを使用してデータを動的に更新する方法が徐々に生まれました。
動的な更新方法はユーザーエクスペリエンスを改善するものの、良いフォームデザインを実現するには多くの細部を考慮する必要があります:
- エラーハンドリング
- ステート遷移
- データの保存
- アクセシビリティ
たとえ一つの要素がうまく機能しない場合、ユーザーは単純なページ全体の更新を行うフォームタグを使用することを好むことがしばしばあります。バックエンドアプリケーションの場合、<form>
タグを使用してページ全体の更新を行うことで、多くの開発時間を節約することができ、さらにブラウザの組み込みメカニズムに依存してより安定した動作を実現できます。
JavaScriptでのFormDataの使用
FormDataは、開発者がキー/値のようなアプリケーションを簡単に作成できるインターフェースを定義しています。最も一般的なのは、フォーム処理です。FormData
の宣言は次のように行います:
const formData = new FormData()
// キー 値
formData.append('name', 'Kalan');
フォームの要素をFormData
に入れると、入力された情報が自動的にFormData
にシリアライズされます:
<form id="form" enctype="multipart/form-data" action="/upload" method="POST">
<input type="text" name="name" />
<input type="file" name="file" />
<button>Submit</button>
</form>
<script>
const formData = new FormData(document.getElementById('form'));
formData.get('name'); // 現在のinputの値を取得
formData.get('file'); // 現在のファイルを取得
</script>
さらに、FormDataをfetchのbodyに入れると、ブラウザが自動的にmultipart/form-data
形式で送信します:
const formData = new FormData();
formData.append('name', 'Kalan');
formData.append('file', new File(['Hello World'], 'file.txt', { type: 'text/plain' }))
fetch('/upload', {
method: 'POST',
body: formData
})
上記のJavaScriptコードを実行し、ネットワークリクエストを観察すると、Content-Typeを特に指定していなくても、ブラウザが自動的にmultipart/form-data
で送信し、フォームデータのシリアライズもブラウザによって行われることがわかります。
結論
これらの2つの記事では、multipart/form-data
の使用と実際の使用方法について説明しました。最初の記事では、Content-Disposition
の意味、boundaryの目的、およびmultipart/form-dataリクエストの構築方法について説明しました。2番目の記事では、実際のプラクティスでformとFormDataをどのように使用し、JavaScriptを使用してFormDataを処理しファイルをアップロードするかについて説明しました。
サーバーサイドでは、Webページ上でのファイルのアップロードもHTTPリクエストとして扱われるため、サーバーサイドはヘッダーの情報とmultipart/form-data
で定義された形式に基づいてデータを解析する必要があります。通常、これらの解析はフレームワークによって処理されていますが、ここで特に注意すべきは、「ファイルの送信はHTTPリクエストの上に基づいており、神秘的な魔法は存在しない」ということです。