XMLHttpRequest Level2 が導入される前は、ほとんどの画像の非同期アップロードは iframe を使用して実装されていました。
具体的な実装の詳細については、私はここにいません。これに関する記事が Google にあります。
今回は主に新しいAPIを使って画像をアップロードする方法について話します。
まず第一に、XMLHttpRequest Level2 のいくつかの新機能が不可欠です。
最も実用的なのは FormData オブジェクトです。これは、フォームの Dom オブジェクトを FormData オブジェクトに直接変換し、それをサーバーに送信します。
Progress イベントもサポートされ、ついに非同期アップロードの進行状況バーを表示できるようになりました。
ここではナンセンスな話はしません。ほとんどの人は Ruan Yifeng の「XMLHttpRequest Level 2 User Guide」を読んでいるはずなので、コードを直接貼り付けるだけです。
1 var formData= new FormData(form),
2 xhr= new XMLHttpRequest();
3
4 xhr.open("POST", url);
5 xhr.send(formData) ;
インターフェイス部分も PHP のように非常にシンプルで、$_POST と $_FILES を使用して直接関連データを取得できます。
進行時間を監視することで、現在のデータのアップロード/ダウンロードの進行状況を確認できます。
1 xhr.upload.onprogress = function (e) {
2 console.log(e.loaded / e.total * 100) // アップロードの進行状況
3 }
4
5 xhr.onprogress = function (e) {
6 console.log(e.loaded / e.total * 100); // ダウンロード進捗状況
7 }
XMLHttpRequest Level2 のサポートについては、まだですモバイル側でさらに理想的。
長い間、数え切れないほどのフロントエンド ブラウザーが、ローカル ファイルにアクセスするための JavaScript 用の API を提供できました。
実は、IE では昔から ActiveX を使ってローカル ファイルを操作することができましたが、W3C 標準ではないため、IE のみで動作していました。
2012 年 10 月 25 日、W3C はファイル API のドラフトを確立しました。
さらに、FileReader オブジェクトは File オブジェクトと組み合わせて使用されます。具体的な使い方については後述します。
以下は二人のサポートであり、状況は比較的平均的です。しかし、最初にそれを学ぶだけでほとんど十分です、は〜
最初に File オブジェクトについて話しましょう。
File オブジェクトは、ユーザーが 要素でファイルを選択した後に返される FileList オブジェクトであるか、
のようなドラッグ アンド ドロップ操作によって生成される DataTransfer オブジェクトである可能性があります。
1 //input:file
2のファイルオブジェクト document.querySelector("input[type=file]").files; // return FileList
3
4 //ドロップのファイルオブジェクトevent
5 elem.ondrop = function (e) {
6 e.preventDefault();
7 return e.dataTransfer.files; // return FileList
8 };
はすべてFileList オブジェクト。この FileList オブジェクトは NodeList に似ています。長さ属性はありますが、配列ではありません。
以下は Chrome コンソールによって出力される FileList オブジェクトです:
File オブジェクトのプロパティを見てみましょう:
非については話しません意味それらのプロパティが何を意味するのか。ただし、File オブジェクトは Blob オブジェクトを継承していることがわかります。Blob オブジェクトとは何かについては、後で説明します。
冒頭で、File オブジェクトと一緒に使用されると言って、FileReader オブジェクトについても触れました。
FileReader オブジェクトを使用すると、Web アプリケーションはユーザーのコンピューターに保存されているファイル (または生データ バッファー) の内容を非同期的に読み取ることができます。 File オブジェクトまたは Blob オブジェクトを使用して、読み取るファイルまたはデータを指定できます。
具体的な使い方を以下のコードで見てみましょう:
1 // FileReader オブジェクトを作成します
2 var Reader = new FileReader();
3
4 // ロードイベントをバインドします
5 Reader.onload = function(e) {
6 console.log(e.target.result);
7 }
8
9 // ファイルのデータを読み取りますobject
10 Reader.readAsDataURL( document.querySelector("input[type=file]").files[0]);
FileReader オブジェクトが readAsDataURL を通じてデータを正常に読み取ると、load イベントがトリガーされます。ターゲットの result 属性の値は、ファイルの Base64 データです。もちろん、FileReader オブジェクトには readAsDataURL という 1 つのメソッドしかありません。
1 /**
2 * 読み取り操作を中止します。戻るとき、readyState 属性の値は DONE です。
3 */
4 Reader.abort();
5
6
7 /**
8 * 指定された Blob オブジェクトまたは File オブジェクトの内容の読み取りを開始します。
9 * 読み取り操作が完了すると、readyState 属性の値が DONE になります。 onloadend イベント ハンドラーが設定されている場合は、それを呼び出します。
10 * 同時に、result 属性には、読み取られたファイルの内容を表す URL 形式の data: 文字列が含まれます。* /12 Reader.readAsDataURL(ファイル);13 14 15 /**16 * 上記と同様に、result 属性には、読み取ったファイルの内容を表す文字列が含まれます。 17 * エンコーディングはオプションで、データを返すために使用されるエンコーディングを示します。指定しない場合、デフォルトは次のとおりです。 UTF-8.18*/19 Reader.readAsText(ファイル [, エンコーディング]); /25 Reader.readAsArrayBuffer(file); 26 27 28 /**23 * 上記と同様に、result 属性には、読み取られたファイルの内容を表す ArrayBuffer オブジェクトが含まれます 24*/31 Reader.readAsBinaryString(file);ファイルを使用すると、作業がはるかに簡単になります。 たとえば、base64 文字列をサーバーに直接ポストできます。 1 var Reader = new FileReader(); 2 3 Reader.onload = function(e) { 4 var xhr = new XMLHttpRequest(), 5 fromData = new FormData() ; 6 7 fromData.append("base64", e.target.result); 8 xhr.open("post",url, true); 9 xhr.send(fromData); 10 }11 12 Reader.readAsDataURL(document.querySelector("input[type=file]").files[0]); 何か問題があると思いますか? FormData を使用しているので、Base64 に変換してみませんか? base64に変換した後の最大の利点は、Canvas上に描画して画像を編集できることです。 クライアント側でトリミングや落書き等を行い、編集が完了したらCanvasオブジェクトのtoDataURLメソッドを使用して編集後の画像のbase64データを出力します。 ここでは実装の詳細には触れません。 HTML5 ファイルフォーム要素によって提供される新しいサポートを見てみましょう: 1 2 accept 属性。制限するために使用できます。ユーザーアップロード ファイルのタイプ。このプロパティは、iOS および OSX で十分にサポートされています。 さらに、multiple 属性があり、複数のファイルを選択できることを意味します。この属性を追加した後、FormData オブジェクトと組み合わせて、バッチ アップロードを実現できます。 1 (function (W, D) { 2 var fileForm = document.getElementById("file_form"), 3 fileImage = document.getElementById("file_image"); 4 5 function testAjax(files, i) { 6 pRequest(),11 data = new FormData( );12 13 17 data.append("file_image", files[i]); 18 xhr.open("post", "test/demo2.php", true);19 xhr.send(data);20 }21 22 fileForm.addEventListener("submit", function ( e) {23 e.preventDefault();24 var files = fileImage.files;25 26 testAjax(files, --files.length);27 }, false);28 29 })(ウィンドウ、ドキュメント);