English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

XMLHttpRequest(二)応答属性、バイナリデータ、アップロードダウンロードの進捗の監視

responseXML属性の分析および操作 

リモートのXMLドキュメントの内容を取得するためにXMLHttpRequestを使用する場合、responseXML属性はXMLドキュメントを解析したDOMオブジェクトとなり、操作や分析が難しいことがあります。XMLドキュメントを分析する主な方法が以下の五つあります:
 1.XPathを使用してドキュメントの特定部分に定位します。
 2.JXONを使用してそれをJavaScriptオブジェクトツリーに変換します。
 3.XMLを手動で解析およびシリアライズして文字列やオブジェクトにします。
 4.XMLSerializerを使用してDOMツリーを文字列やファイルにシリアライズします。
 5.もし XML 文書の内容を事前に知っている場合、RegExp を使用できます。もし RegExp でスキャンを行う際に改行符が影響を与える場合、すべての改行符を削除したいかもしれません。しかし、この方法は「最終手段」です。なぜなら、XML コードが少しでも変わると、この方法は失敗する可能性があるからです。 

HTML ドキュメントを含む responseText 属性の解析および操作 

注意: 在 W3C XMLHttpRequest 規範では、HTML が XMLHttpRequest.responseXML 属性を通じて解析されることを許可しています。詳細については、HTML in XMLHttpRequest を参照してください。
 XMLHttpRequest を使用して遠端から HTML ページを取得する場合、すべての HTML マークアップは responseText 属性として文字列の形式で保存されます。これにより、これらのマークアップの操作と解析が難しくなります。これらの HTML マークアップを解析する方法には主に 3 つの方法があります:
 1.XMLHttpRequest.responseXML 属性を使用します。
 2.内容を fragment.body.innerHTML に注入し、ドキュメントフラグメント内の DOM を巡回します。
 3.もし HTML 文書の内容を事前に知っている場合、RegExp を使用できます。もし RegExp でスキャンを行う際に改行符が影響を与える場合、すべての改行符を削除したいかもしれません。しかし、この方法は「最終手段」です。なぜなら、HTML コードが少しでも変わると、この方法は失敗する可能性があるからです。 

Handling binary data 

XMLHttpRequest は一般的にテキストデータの送信と受信に使われますが、実はバイナリコンテンツも送信および受信できます。バイナリデータを強制的に XMLHttpRequest で送信するための多くのテスト済みの方法があります。XMLHttpRequest の .overrideMimeType() メソッドは一つの解決策ですが、これは標準的な方法ではありません。

 var oReq = new XMLHttpRequest();
oReq.open("GET", url, true);
// retrieve data unprocessed as a binary string
oReq.overrideMimeType("text/plain; charset=x-user-defined");
/* ... */ 

在 XMLHttpRequest レベル 2 規範に新しい responseType 属性が追加されました。これにより、二進数データの送信と受信がより簡単になります。

 var oReq = new XMLHttpRequest();
oReq.onload = function(e) {
 var arraybuffer = xhr.response; // not responseText
 /* ... */
}
oReq.open("GET", url, true);
oReq.responseType = "arraybuffer";
oReq.send(); 

使用JavaScript类型数组接受二进制数据 

可以通过设置一个XMLHttpRequest对象的responseType属性来改变一个从服务器上返回的响应的数据类型.可用的属性值为空字符串 (默认), "arraybuffer", "blob", "document", 和 "text". response属性的值会根据responseType属性的值的不同而不同, 可能会是一个 ArrayBuffer, Blob, Document, string,或者为NULL(如果请求未完成或失败)
 下例读取了一个二进制图像文件,并且由该文件的二进制原生字节创建了一个8位无符号整数的数组.

 var oReq = new XMLHttpRequest();
oReq.open("GET", "/
oReq.responseType = "arraybuffer";
oReq.onload = function (oEvent) {
 var arrayBuffer = oReq.response; // 注意:不是oReq.responseText
 if (arrayBuffer) {
  var byteArray = new Uint8Array(arrayBuffer);
  for (var i = 0; i < byteArray.byteLength; i++) {
   // 对数组中的每个字节进行操作
  }
 }
};
oReq.send(null); 

除了上面的方法,还可以使用 BlobBuilder API 直接将arraybuffer数据添加进一个Blob对象中, 由于该API还在试验阶段,所以需要加上特定的前缀:

 var BlobBuilder = window.MozBlobBuilder || window.WebKitBlobBuilder || window.MSBlobBuilder || window.BlobBuilder;
var oReq = new XMLHttpRequest();
oReq.open("GET", "/
oReq.responseType = "arraybuffer";
oReq.onload = function(oEvent) {
 var blobBuilder = new BlobBuilder();
 blobBuilder.append(oReq.response);
 var blob = blobBuilder.getBlob("image", "myfile.png", true);/png");
 // ...
};
oReq.send(); 

古いブラウザでのバイナリデータの受信
 以下のload_binary_resource()メソッドは指定されたURLからバイナリデータをロードし、データを呼び出し元に返します。

 function load_binary_resource(url) {
 var req = new XMLHttpRequest();
 req.open('GET', url, false);
 //XHRバイナリ文字セットオプション by Marcus Granado 2006 [http://mgran.blogspot.com]
 req.overrideMimeType('text/plain; charset=x-user-defined\');
 req.send(null);
 if (req.status != 200) return '';
 return req.responseText;
} 

最も面白い操作は第5行にあります。この行ではデフォルトのMIMEタイプを上書きし、ブラウザがその応答を純テキストファイルとして処理するように強制します。ユーザー定義の文字セットを使用して、ブラウザにデータを解析しないように指示します。これにより、ブラウザに未処理のバイトコードを直接返すように教えます。

 var filestream = load_binary_resource(url);
var abyte = filestream.charCodeAt(x) & 0xff; // 捨てられた高位バイト(f7) 

上記の例では、リクエストから戻ってきたバイナリデータからオフセットがxの位置にあるバイトを取得しました。有効なオフセット範囲は0からfilestream.lengthです。-1.
 詳細は「使用XMLHttpRequestでファイルをダウンロードする」を参照してください。

 バイナリデータの送信

 XMLHttpRequestオブジェクトのsendメソッドは強化され、ArrayBuffer、Blob、またはFileオブジェクトを簡単に渡すことでバイナリデータを送信できます。
 以下の例では、テキストファイルを作成し、POSTメソッドでそのファイルをサーバーに送信しました。他のバイナリデータ形式のテキストファイル以外も使用できます。

 var oReq = new XMLHttpRequest();
oReq.open("POST", url, true);
oReq.onload = function (oEvent) {
 // アップロードが完了した後.
};
var bb = new BlobBuilder(); // require appropriate prefixes: window.MozBlobBuilder or window.WebKitBlobBuilder
bb.append(\'abc123\');
oReq.send(bb.getBlob(\'text/plain\')); 

Send typed arrays as binary data
 You can send JavaScript typed arrays as binary data.

 var myArray = new ArrayBuffer(512);
var longInt8View = new Uint8Array(myArray);
for (var i=0; i< longInt8View.length; i++) {
 longInt8View[i] = i % 255;
}
var xhr = new XMLHttpRequest;
xhr.open("POST", url, false);
xhr.send(myArray); 

For example, a new512bytes8send it as a byte integer array, of course, you can also send any binary data

 监测进度
 Support for the progress event of DOM for XMLHttpRequest transmission, following the Web API progress event specification: these events implement the ProgressEvent interface.

 var req = new XMLHttpRequest();
//上传监听
req.addEventListener("progress", updateProgress, false);
req.addEventListener("load", transferComplete, false);
req.addEventListener("error", transferFailed, false);
req.addEventListener("abort", transferCanceled, false);
req.open(...);
...
// progress on transfers from the server to the client (downloads)
function updateProgress(evt) {
 if (evt.lengthComputable) {
  var percentComplete = evt.loaded / evt.total;
  ...
 }
  // 総サイズが未知であるため、進捗情報を計算できません。
 }
} 

注意:open()メソッドの呼び出しの前にイベントリスナーを追加する必要があります。そうしないと、progressイベントはトリガーされません。
 前の例では、progressイベントがupdateProgress()関数で指定され、転送の総バイト数totalと既に転送されたバイト数loadedを受け取ります。totalは「Content」から始まる場所までの長さです。-“Length”ヘッダーが転送するデータの全体の長さ(バイト)。しかし、lengthComputable属性の値がfalseの場合、総バイト数は未知でtotalの値は0となります。長さが知られている場合、lengthComputable属性はtrueになります。
 progressイベントはダウンロードとアップロードの転送の両方に存在します。ダウンロードに関連するイベントは、上記の例のようにXMLHttpRequestオブジェクト上でトリガーされます。アップロードに関連するイベントは、以下のようにXMLHttpRequest.uploadオブジェクト上でトリガーされます:

 var req = new XMLHttpRequest();
//ダウンロードリスナー
req.upload.addEventListener("progress", updateProgress);
req.upload.addEventListener("load", transferComplete);
req.upload.addEventListener("error", transferFailed);
req.upload.addEventListener("abort", transferCanceled);
req.open(); 

注意:progressイベントはfile:プロトコルの使用では無効です。
 loadendイベントを使用して、すべての3つのロード終了条件(abort、load、error)を検出できます:
 req.addEventListener("loadend", loadEnd, false);
 注意が必要です。loadendイベントが受け取った情報がどの条件による操作の終了から来たのかを正確に知る方法はありませんが、すべての転送が終わったときにこのイベントを処理することができます。 

XMLHttpRequestオブジェクトはリクエストの異なる段階で異なるタイプのイベントをトリガーするため、readyState属性をチェックする必要はありません。
 send()を呼び出すと、単一のloadstartイベントがトリガーされます。サーバーの応答をロードしている間、XMLHttpRequestオブジェクトはprogressイベントを発生させ、通常は5約0ミリ秒で、これらのイベントを使用してユーザーにリクエストの進捗をフィードバックすることができます。
 リクエストが速く完了する場合、progressイベントは発生しません。イベントが完了すると、loadイベントがトリガーされます。
 あります。3HTTPリクエストが完了できない理由には、3これらのイベントが発生すると、以下の状況に対応します。
 特定のリクエストに対して、ブラウザはload、abort、timeout、errorイベントのうちの1つ、またはprogressイベントをトリガーします。

 if(\'onprogress\' in (new XMLHttpRequest())){ //progressイベントのサポートを確認
  var request = new XMLHttpRequest();
  request.onprogress = function (e) {
    if(e.lengthComputable){
      progress.innerHTML = Math.round(100* e.loaded/ e.total) + \'%\';
    }
  }
}

これでこの記事のすべての内容が終わります。皆様の学習に役立つことを願っています。また、呐喊チュートリアルを多くのサポートをお願いします。

声明:この記事の内容はインターネットから取得され、著作権者に帰属します。インターネットユーザーが自発的に貢献し、自己でアップロードしたものです。このサイトは所有権を持ちません。人工的な編集は行われていません。また、関連する法的責任を負いません。著作権侵害が疑われる内容を見つけたら、メールを送信してください:notice#oldtoolbag.com(メール送信時は、#を@に変更して報告してください。関連する証拠を提供し、一旦確認ができたら、このサイトは即座に侵害疑いのコンテンツを削除します。)

基本チュートリアル
おすすめ