本日はそんな方に向けてJavaScriptでのファイルアップロードの作り方を解説します。この記事では、Requestオブジェクト、Headers、Response、fetch関数、そしてFileListなど、JavaScriptでファイルアップロードを行うための主要な概念と手法に焦点を当てます。どのようにしてこれらの要素を組み合わせ、効果的に利用するかについて解説していきましょう。ファイルアップロードはユーザーがコンテンツを共有し、ウェブアプリケーションがより対話的でパワフルなものになる際の重要なステップで実装するのが当たり前になりました。初心者の方もスルーできない内容なので、この機会にJavaScriptを使ったファイルアップロードの基本から実践的な応用までを順を追って練習しましょう。動画もあるので必要に応じて活用してください。JavaScriptを使ったファイル添付〜アップロードの作り方【単体】まずは基本となる単体のファイル添付についてです。そもそもフォームにおいてファイル添付はinputタグのtype属性をfileにすることで専用のボタンを画面に表示することができます。クリックするとMacであればFinder、Windowsであればエクスプローラーが展開されてユーザーが添付したいファイルを選択することができます。選択したファイルはfilesという配列のプロパティで取得することができます。console.log(files);});FileListという配列になっていることがわかります。インデックス番号0番目にオブジェクト形式で選択したファイルが格納されています。こちら配列になっているのがポイントで、以下のようにすればファイル添付が成功したかを検証することもできます。}});配列の要素が1個以上なければファイル添付がされてないということになりますね。後で解説しますが複数のファイル添付の際にはインデックス番号が順番に振られてオブジェクト形式で格納されます。ファイルサイズ」を確認することができます。配列なのでインデックス番号を指定するのを忘れないようにしましょう。}});なんとなくファイル添付の仕組みがわかってきたところで、実務でありがちなアップロードをやってみます。今回はjsonplaceholderというテスト送信が可能なAPIを使用して、パソコンにあるjsonデータをfetchメソッドで送ってみましょう。実際にはURLは実際には送信できませんがコピペしてください。}});アップロードするときのfetchメソッドの引数は以上3点、body(データ)とmethod(命令)とheaders(ヘッダー)です。それらはRequest()というクラスをインスタンス化するとオブジェクトとして3点をまとめることができます。Requestクラスのbodyプロパティにfiles[0]を指定すれば先ほどのオブジェクト形式を選択したことになります。methodプロパティはアップロードなのでPOSTを指定します。headersプロパティは先ほどコンソールで確認した「ファイルサイズ」「ファイルの種類」にしてみました。Headers()というクラスをインスタンス化してappendメソッドで好きな項目をヘッダーに含めることができるので、files[0].typeとfiles[0].sizeを指定しています。最後にmodeというプロパティに”no-cors”を指定しましたが、こちらはCORSエラーの回避するものです。fetchメソッドでstatusとstatusTextを返すように指定したので上図のような結果になっているかと思います。エラーが表示されていなければOKです。jsonデータでない画像などを指定するとエラーが表示されますので添付する形式も確認して試してください。続いて2個以上のファイルを添付したいときの実装方法です。データの取得は単体と同じでFileListという配列にインデックス番号で分けられたオブジェクト形式で格納されます。単体のときは0番目しか使わなかったのを1番目、2番目とファイル数に応じてインデックス番号が増えていく感じです。HTML側のinputタグにはmultipleという属性を追加しておくことが必要です。</body></html>ついでにお話しておくとacceptという属性もあって、こちらで添付できるファイル形式を限定させることも可能です。今回もjsonファイルを使用したいのでaccept=”.json”と書いてみます。ファイル添付する際に画像データなどが選択できないようになっているはずです。</body></html>それでは一度2個のjsonファイルを選択して添付してみましょう。コンソールには以下のように表示されるかと思います。}});単体のときと違ってオブジェクトが2個あるのがわかりますね。どっちがどっちかというのはnameプロパティにファイル名があるのでnameで判断できます。アップロード機能については先ほどの単体の時を同じなので以下のように書くことで複数添付の送信が可能です。1点だけ違うのが複数添付ではヘッダーを書くことができないので、FormDataクラスをインスタンス化してFormDataクラスが自動で生成するヘッダーが使用されることになります。Request()のbodyにはデータ本体(files[0]など)を書くと前章で話しましたが、こちらにはFormDataをインスタンス化した変数を入れます。}});今回も上図のような結果になるはずです。1つでも2つでも大枠の仕組みは同じなので、どちらのパターンも練習しておくことをお勧めします。サーバーやメールに実際に送信するにはバックエンドの知識が必要になります。実務では担当が別であることが多いので初心者の方は本記事の内容をまずは理解することを優先すると良いでしょう。JavaScriptでアップロードした時のレスポンスについてここまでアップロード機能の作り方を解説してきましたが、何かしらデータを投稿したときはレスポンスが返ってきていることを知っていますか?冷静に考えてみると送信が毎回成功するとは限りませんよね。何かの理由で正常に送信できなかったとき、ユーザーや開発者が知る必要がありレスポンスというオブジェクトを持ってJavaScriptは知らせてくれます。先ほどのコードを一部修正してみましょう。}});fetchしたときにres.statusとしていたところをresというオブジェクト全体でコンソールに表示させてみます。2つのjsonファイルを添付してみると以下のような形になるはずです。statusとstatusTextというのはResponseオブジェクトの中のプロパティの一部だったことがわかりますね。このように何かを送信したときにはレスポンスが返ってくることを初心者の方は覚えておきましょう。バックエンドの言語を勉強したことがある方であれば「リクエストとレスポンス」というキーワードを聞いたことがあるはずです。JavaScriptはマルチな言語でフロントエンドだけでなくサーバーとのやり取りまで対応させることができますので、今後バックエンドをJavaScriptを使うときにレスポンスの仕組みを知っておくと学習が進むでしょう。Responseというクラスがあるので大枠は同じような構文を書きます。});先ほどの例題ではなく新しくシンプルなオブジェクトを取り扱うなかでResponseを練習してみます。オブジェクトをJSON形式にして送信したものを、逆にJSONからオブジェクトに戻すだけのコードを書きます。FileでFileオブジェクトを使用します。Responseでインスタンス化して返します。console.log(response);}Responseオブジェクトはstatusプロパティに受信できたかを特定の数字で表現します。200とすると成功した意味になります。数字だとわかりづらいのでstatusTextというプロパティには文字列で何か書くことが多いです。Responseオブジェクトでもヘッダー情報が必要になり、こちらはファイル添付のときと同じで「ファイルの種類」「ファイルサイズ」などを記載することが一般的です。コンソールを確認するとインスタンス化したResponseオブジェクトが表示されます。このプログラムではオブジェクトがJSON形式に変換されて受け取った想定なので、逆にJSON形式からオブジェクトに戻しましょう。console.log(data);}Responseオブジェクトには受け取ったデータが格納されているのでjson()などメソッドを使って値を取り出すことができます。本記事ではサーバーを使用せず「自分で送って自分に返す」ようなことをしていますが、実際にファイル添付した画像をプレビューする機能でも「自分で送って自分で返したものをプレビューする」ことをやっています。新しくHTML、JSを書き直して確認してみましょう。url;});JavaScriptの前半部分は先ほどと同じくResponseクラスをインスタンス化しているだけです。続いてResponseオブジェクトを先ほどはJSON形式からオブジェクトに戻すためにjson()を使いました。今回は画像データということでURLが欲しいので、blob()でBlob形式に変換してからURL.createObjectURL()で画像を表示するURLを生成しています。あとはHTML側で用意していたaタグのhrefの値に代入すればOKです。JavaScriptで画像添付の際にリサイズして送信する方法これまで画像の添付と送信をやってきましたが、画像をリサイズしてから送りたい場面があります。いろんな画像があり容量の大きいものがあるときはリサイズで小さくしたほうが送りやすいからです。</body></html>前章までのおさらいでinputタグを経由して画像をアップロードして画面に表示するまでは以下のようなコードになります。};});例えば以下の画像は1024×1024サイズの大きめの素材ですので、2.3MBの容量があります。こちらの画像を400×400までリサイズして容量を減らすことをやってみます。画像のリサイズはcanvasを使ったやり方です。};});HTML上にimgタグを使ってプレビュー画面を作っていましたがcanvasタグを使うことでサイズの変更ができます。こちらで再度アップロードしてみると400×400までリサイズされていて容量も1MBを切るように減らすことができました。ちなみにCSSで表示範囲を小さくすることでプレビュー自体は小さくなりますが、画像の素材自体が小さくなっているわけではないのでCSSではリサイズはできません。リサイズした画像を送信するコードは以下のようになります。現時点では上図のようにbase64形式のURLになっているのでファイルに戻します。file;}base64形式のURLをファイル形式に戻す関数をconvertFileとして別の関数で作りました。不要な文字をsplitメソッドと正規表現を使ってトリミングした後は、atobメソッドというものを使うことで暗号化されたbase64を復号化することができます。Fileでインスタンス化することでファイル形式になります。convertFIle関数を実行した後にconsole.logで変換後のデータを表示するようにしているので、ブラウザをリロードして再度アップロードしてコンソールを確認します。Fileオブジェクトが表示されていることからファイル形式に戻っていることがわかります。続いてファイル形式に戻したデータを送信する処理をuploadImgという関数にして作ります。.catch(console.warn);}FormDataをインスタンス化して送信するためのファイルを先ほど変換済みのFileデータにします。続いてRequestをインスタンス化してURLとメソッドの指定をする流れは前章の内容と同じになります。送信する前にリサイズしておくことがポイントで、プレビュー画面があるとデータが一度URLになっている場合が多く、URLから再度ファイル形式に戻す変換作業が必要になります。手順は多いですが基本的な仕組みはファイルとリクエストとレスポンスの標準クラスを使って実現できます。このようにファイル添付を通じてリクエストとレスポンスを一緒に実装できるので、初心者の方も良い題材としてファイル添付の機能を自身のポートフォリオなどで作ってみてはいかがでしょうか。今回参考にした本はこちらになります。