web-dev-qa-db-ja.com

サーバーからファイルをダウンロードしてサンドボックスに保存するHTML5 File API

HTML5 APIを理解しようとしています。ブラウザクライアントがサーバーから複数のファイルをダウンロードする必要があるWebアプリケーションを設計しています。ユーザーは、ダウンロードしたファイルとアプリケーションを使用して、ユーザーの状態を保存する必要があります。ユーザーがアプリケーションを2回目に起動したときにこれらのファイルを取得できる限り、ブラウザーはサンドボックスにのみこれらのファイルを保存できることを理解しています。 BlobBuilderまたはFileSaverを使用する必要がありますか?私はここで少し迷っています。

28
Mamadum

XMLHttpRequest Level 2 でファイルをダウンロードし、 FileSystem API または FileSaverインターフェース で保存する方法を紹介します。

ファイルをダウンロードする

ファイルをダウンロードするには、XMLHttpRequest Level 2(別名XHR2)を使用します。これは、クロスオリジンリクエスト、進捗イベントのアップロード、バイナリデータのアップロード/ダウンロードをサポートします。投稿「 XMLHttpRequest2の新しいトリック 」には、XHR2の使用例がたくさんあります。

ファイルをblobとしてダウンロードするには、responseTypeを「blob」に指定するだけです。 「text」、「arraybuffer」、または「document」タイプも使用できます。以下の関数は、url内のファイルをダウンロードし、successコールバックに送信します。

function downloadFile(url, success) {
    var xhr = new XMLHttpRequest(); 
    xhr.open('GET', url, true); 
    xhr.responseType = "blob";
    xhr.onreadystatechange = function () { 
        if (xhr.readyState == 4) {
            if (success) success(xhr.response);
        }
    };
    xhr.send(null);
}

successコールバックは、引数としてBlobのインスタンスを受け取ります。このインスタンスは、後で変更、保存、またはサーバーにアップロードできます。

FileSystem APIを使用してファイルを保存する

使用できます...サイト 指摘 FileSystem APIをサポートするブラウザはあまりありません。 Firefoxの場合 説明があります サポートの欠如。そのため、これを行うにはChromeを使用する必要があります。

まず、ストレージスペースをリクエストする必要があります。ストレージスペースは一時的なものでも永続的なものでもかまいません。おそらく永続ストレージが必要になります。この場合、前もってストレージスペースのクォータをリクエストすることになります( 一部の事実 ):

window.requestFileSystem  = window.requestFileSystem || window.webkitRequestFileSystem;
window.storageInfo = window.storageInfo || window.webkitStorageInfo;

// Request access to the file system
var fileSystem = null         // DOMFileSystem instance
  , fsType = PERSISTENT       // PERSISTENT vs. TEMPORARY storage 
  , fsSize = 10 * 1024 * 1024 // size (bytes) of needed space 
  ;

window.storageInfo.requestQuota(fsType, fsSize, function(gb) {
    window.requestFileSystem(fsType, gb, function(fs) {
        fileSystem = fs;
    }, errorHandler);
}, errorHandler);

ファイルシステムにアクセスできるようになったので、ファイルシステムからファイルを保存および読み取ることができます。以下の関数は、指定されたパスのblobをファイルシステムに保存できます。

function saveFile(data, path) {
    if (!fileSystem) return;

    fileSystem.root.getFile(path, {create: true}, function(fileEntry) {
        fileEntry.createWriter(function(writer) {
            writer.write(data);
        }, errorHandler);
    }, errorHandler);
}

パスでファイルを読み取るには:

function readFile(path, success) {
    fileSystem.root.getFile(path, {}, function(fileEntry) {
        fileEntry.file(function(file) {
            var reader = new FileReader();

            reader.onloadend = function(e) {
                if (success) success(this.result);
            };

            reader.readAsText(file);
        }, errorHandler);
    }, errorHandler);
}

readAsTextメソッドに加えて、 FileReader API に従って、readAsArrayBufferおよびreadAsDataURLを呼び出すことができます。

FileSaverを使用する

投稿「 クライアント側で生成されたファイルを保存する 」は、このAPIの使用法を非常によく説明しています。一部のブラウザでは、saveAsインターフェイスを使用するために FileSaver.js が必要になる場合があります。

downloadFile関数と一緒に使用すると、次のようになります。

downloadFile('image.png', function(blob) {
    saveAs(blob, "image.png");
});

もちろん、ユーザーが画像を視覚化し、それを操作し、それを自分のドライブに保存できれば、より意味があります。

エラーハンドラー

例を実現するために:

function errorHandler(e) {
    var msg = '';

    switch (e.code) {
        case FileError.QUOTA_EXCEEDED_ERR:
            msg = 'QUOTA_EXCEEDED_ERR';
            break;
        case FileError.NOT_FOUND_ERR:
            msg = 'NOT_FOUND_ERR';
            break;
        case FileError.SECURITY_ERR:
            msg = 'SECURITY_ERR';
            break;
        case FileError.INVALID_MODIFICATION_ERR:
            msg = 'INVALID_MODIFICATION_ERR';
            break;
        case FileError.INVALID_STATE_ERR:
            msg = 'INVALID_STATE_ERR';
            break;
        default:
            msg = 'Unknown Error';
            break;
    };

    console.log('Error: ' + msg);
}

便利なリンク

66
mayconbordin

HTML5ブラウザーのみをサポートしている場合、使用できる「ダウンロード」属性があります。詳細はこちら: http://updates.html5rocks.com/2011/08/Downloading-resources-in-HTML5-a-download

2
Trunal Bhanse

私のコツは、複数のダウンロードを指す「src」属性を持つIFRAMEを単に追加することです。サーバーサイトは、「disposition:attachment」ヘッダー付きのファイルを送信する必要があり、クライアントはファイルをローカルに保存しようとします。唯一の「問題」は、ユーザーがページを離れるか、ページをリロードするまで、IFRAMEがごみとしてDOMツリーにとどまることです。 IFRAMEを非表示にします(例:width = 0; height = 0;)。準備完了です!すべてのブラウザ。

0
Martin Rode