web-dev-qa-db-ja.com

HTML 5 / JavaScriptを使ってファイルを生成して保存する

私は最近WebGLをいじっていて、Colladaの読者が働いています。問題はそれがかなり遅いということです(Colladaは非常に冗長なフォーマットです)、それで私はファイルをより使いやすいフォーマット(おそらくJSON)に変換し始めるつもりです。 JavaScriptでファイルを解析するためのコードをすでに持っているので、私はそれを私のエクスポーターとしても使うことができます!問題は保存されています。

これで、ファイルを解析し、その結果をサーバーに送信し、ブラウザにダウンロードとしてサーバーからファイルを要求することができるようになりました。しかし、実際にはサーバーはこの特定のプロセスとは無関係です。目的のファイルの内容は既にメモリにあります。純粋なJavaScriptを使用してユーザーにダウンロードを提示する方法はありますか? (私はそれを疑います、しかし同様に尋ねるかもしれません...)

そして明確にするために:私はユーザーの知らないうちにファイルシステムにアクセスしようとしているのではありません!ユーザーは(おそらくドラッグアンドドロップで)ファイルを提供し、スクリプトはメモリ内のファイルを変換し、ユーザーは結果をダウンロードするように促されます。ブラウザに関する限り、これらすべては「安全な」活動であるべきです。

[編集]: 前もって言及しなかったので、 "Flash"と答えたポスターは十分に有効ですが、私がやっていることの一部は純粋なHTML5で何ができるかを強調するための試みです...だからFlashは私の中では正直です。場合。 (それは「本物の」Webアプリを使っている人には完全に有効な答えですが。)そういうわけで、私はサーバーを関与させたくない限り、私は運が悪くなっているようです。とにかくありがとう!

293
Toji

MatthewとDennksterがその選択肢を指摘してくれたおかげで、data:URIを作ることは間違いなく私にとってトリックです!これが基本的に私のやり方です:

1)すべてのコンテンツを「コンテンツ」と呼ばれる文字列にする(例えば、最初にそれを作成することによって、または既に構築されたページのタグのinnerHTMLを読み取ることによって)。

2)データURIを構築します。

uriContent = "data:application/octet-stream," + encodeURIComponent(content);

ブラウザの種類などによっては長さに制限があります。 Firefox 3.6.12は少なくとも256kまで動作します。代わりにencodeURIComponentを使用してBase64でエンコードすると効率が良くなる可能性がありますが、私にとってはそれで問題ありませんでした。

3)新しいウィンドウを開き、このURIに「リダイレクト」すると、JavaScriptで生成されたページのダウンロード場所が求められます。

newWindow = window.open(uriContent, 'neuesDokument');

それでおしまい。

246
Nøk

HTML5対応ブラウザ用のシンプルなソリューション...

function download(filename, text) {
    var pom = document.createElement('a');
    pom.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(text));
    pom.setAttribute('download', filename);

    if (document.createEvent) {
        var event = document.createEvent('MouseEvents');
        event.initEvent('click', true, true);
        pom.dispatchEvent(event);
    }
    else {
        pom.click();
    }
}

使い方

download('test.txt', 'Hello world!');
257
Matěj Pokorný

HTML5はwindow.saveAs(blob, filename)メソッドを定義しました。現在どのブラウザでもサポートされていません。しかし、 FileSaver.js と呼ばれる互換性ライブラリがあり、これが最近のほとんどのブラウザ(Internet Explorer 10以降を含む)に追加されています。 Internet Explorer 10は、Internet ExplorerをサポートするためにFileSaver.jsで使用されるnavigator.msSaveBlob(blob, filename)メソッド( MSDN )をサポートしています。

私は ブログ投稿 を書き、この問題に関する詳細を書いています。

79
panzi

大きなファイルを保存する

長いデータURIはブラウザのパフォーマンス上の問題を引き起こす可能性があります。クライアントサイドで生成されたファイルを保存するもう1つのオプションは、それらの内容をBlob(またはFile)オブジェクトに入れ、 URL.createObjectURL(blob) を使用してダウンロードリンクを作成することです。これは、BLOBの内容を取得するために使用できるURLを返します。 BLOBは、URLでURL.revokeObjectURL()が呼び出されるか、それを作成した文書が閉じられるまで、ブラウザ内に保存されます。ほとんどのウェブブラウザは でオブジェクトURLをサポートしています 、Opera Miniはそれらをサポートしていない唯一のものです。

ダウンロードを強制する

データがテキストまたはイメージの場合、ブラウザはファイルをディスクに保存する代わりにそのファイルを開くことができます。リンクをクリックしたときにファイルがダウンロードされるようにするには、download属性を使用できます。ただし、すべてのWebブラウザで がダウンロード属性 をサポートしているわけではありません。別のオプションは、ファイルのMIMEタイプとしてapplication/octet-streamを使用することですが、これはファイルをバイナリBLOBとして表示させます。ファイル名を指定しない場合、または指定できない場合は特にユーザーに不便です。 ' HTMLでテキストリンクをクリックしてクリックすると、[名前を付けて保存...]ポップアップが強制的に開かれます

ファイル名の指定

BLOBがFileコンストラクタで作成されている場合は、ファイル名を設定することもできますが、 のFileコンストラクタ をサポートしているWebブラウザはいくつかあります。ファイル名をdownload属性への引数として指定することもできますが、これは セキュリティ上の考慮事項 のトン数の影響を受けます。 Internet Explorer 10および11には、ファイル名を指定するための独自のメソッド msSaveBlob が用意されています。

コード例

var file;
var data = [];
data.Push("This is a test\n");
data.Push("Of creating a file\n");
data.Push("In a browser\n");
var properties = {type: 'text/plain'}; // Specify the file's mime-type.
try {
  // Specify the filename using the File constructor, but ...
  file = new File(data, "file.txt", properties);
} catch (e) {
  // ... fall back to the Blob constructor if that isn't supported.
  file = new Blob(data, properties);
}
var url = URL.createObjectURL(file);
document.getElementById('link').href = url;
<a id="link" target="_blank" download="file.txt">Download</a>
42
bcmpinc
function download(content, filename, contentType)
{
    if(!contentType) contentType = 'application/octet-stream';
        var a = document.createElement('a');
        var blob = new Blob([content], {'type':contentType});
        a.href = window.URL.createObjectURL(blob);
        a.download = filename;
        a.click();
}
32
Yassir Ennazk

これを行うためのFlashベースのJavaScriptインターフェースであるDoug Neinerの Downloadify を見てください。

Downloadifyは、サーバーとのやり取りなしに、ブラウザ内でファイルの生成と保存を可能にする小さなJavaScript + Flashライブラリです。

25
Pekka 웃

簡単な解決策!

<a download="My-FileName.txt" href="data:application/octet-stream,HELLO-WORLDDDDDDDD">Click here</a>

最近のすべてのブラウザで動作します。

16
T.Todua

私はFileSaver( https://github.com/eligrey/FileSaver.js )を使用しましたが、問題なく動作します。
例えば、ページに表示されているログをエクスポートするためにこの機能を実行しました。
あなたはBlobのインスタンス化のために配列を渡さなければならないので、私は多分これを正しい方法で書いていないかもしれませんが、それは私のために働きます。
念のため、置き換えに注意してください。これは、このグローバルにするための構文です。それ以外の場合は、最初に出会ったものだけを置き換えます。

exportLogs : function(){
    var array = new Array();

    var str = $('#logs').html();
    array[0] = str.replace(/<br>/g, '\n\t');

    var blob = new Blob(array, {type: "text/plain;charset=utf-8"});
    saveAs(blob, "example.log");
}
10
Razakhel

あなたは データURI を生成することができます。ただし、ブラウザ固有の制限があります。

10

私は自分に役立つ2つの簡単なアプローチを見つけました。まず、クリック済みのa要素を使用してダウンロードデータを挿入します。そして次に、ダウンロードデータを使ってa要素を生成し、a.click()を実行してそれを削除します。しかし、2番目の方法は、ユーザーのクリック操作によっても呼び出される場合にのみ機能します。 (一部)ブラウザはロード時やタイムアウト(setTimeout)後にトリガされた場合など、他のコンテキストからclick()をブロックします。

<!DOCTYPE HTML>
<html>
  <head>
    <meta charset="UTF-8">
    <script type="text/javascript">
      function linkDownload(a, filename, content) {
        contentType =  'data:application/octet-stream,';
        uriContent = contentType + encodeURIComponent(content);
        a.setAttribute('href', uriContent);
        a.setAttribute('download', filename);
      }
      function download(filename, content) {
        var a = document.createElement('a');
        linkDownload(a, filename, content);
        document.body.appendChild(a);
        a.click();
        document.body.removeChild(a);
      }
    </script>
   </head>
  <body>
    <a href="#" onclick="linkDownload(this, 'test.txt', 'Hello World!');">download</a>
    <button onclick="download('test.txt', 'Hello World!');">download</button>
  </body>
</html>
8
maikel

ここにMathewが提案したデータのURIメソッドへのリンクがあります。これはsafariで動作しましたが、ファイルタイプを設定できなかったためうまくいきませんファイルを表示するには...

http://www.nihilogic.dk/labs/canvas2image/

6
Dennkster

LocalStorageを使うことができます。これはHtml5に相当するクッキーです。 ChromeとFirefoxでは動作しますが、Firefoxでは動作します。サーバーにアップロードする必要がありました。つまり、自宅のコンピュータで直接テストしてもうまくいきませんでした。

私はHTML5の例を作り上げています。 http://faculty.purchase.edu/jeanine.meyer/html5/html5explain.html に移動して迷路をスクロールします。迷路を再構築するための情報はlocalStorageを使って保存されます。

私はこの記事に来て、xmlファイルをロードして作業するためのHTML5 JavaScriptを探しました。それは古いHTMLやJavaScriptと同じですか???

4
Jeanine

前述のように、 File API、 FileWriter および FileSystem APIを使用できます。ブラウザのタブ/ウィンドウのコンテキストからクライアントのマシンにファイルを保存します。

しかし、注意が必要な後者の2つのAPIに関するいくつかのことがあります。

  • APIの実装は現在Chromiumベースのブラウザ(Chrome&Opera)にのみ存在します。
  • どちらのAPIも、2014年4月24日にW3C標準化過程から削除されました。現時点では独自のものです。
  • 将来ブラウザを実装することから(現在は独自の)APIを削除する可能性があります
  • サンドボックス(ファイルの外部には影響を与えないディスク上の場所)は、APIで作成されたファイルを格納するために使用されます。
  • APIを使用して作成されたファイルは、仮想ファイルシステム(ブラウザ内からアクセスしたときと同じ形式でディスク上に存在するとは限らないディレクトリ構造)が使用されます。

これを行うために、直接的および間接的にAPIがどのように使用されるかの簡単な例を次に示します。

BakedGoods *

bakedGoods.get({
        data: ["testFile"],
        storageTypes: ["fileSystem"],
        options: {fileSystem:{storageType: Window.PERSISTENT}},
        complete: function(resultDataObj, byStorageTypeErrorObj){}
});

生のFile、FileWriter、およびFileSystem APIの使用

function onQuotaRequestSuccess(grantedQuota)
{

    function saveFile(directoryEntry)
    {

        function createFileWriter(fileEntry)
        {

            function write(fileWriter)
            {
                var dataBlob = new Blob(["Hello world!"], {type: "text/plain"});
                fileWriter.write(dataBlob);              
            }

            fileEntry.createWriter(write);
        }

        directoryEntry.getFile(
            "testFile", 
            {create: true, exclusive: true},
            createFileWriter
        );
    }

    requestFileSystem(Window.PERSISTENT, grantedQuota, saveFile);
}

var desiredQuota = 1024 * 1024 * 1024;
var quotaManagementObj = navigator.webkitPersistentStorage;
quotaManagementObj.requestQuota(desiredQuota, onQuotaRequestSuccess);

FileSystemとFileWriterのAPIはもはや標準化されていませんが、私の意見では、それらの使用はいくつかのケースでは正当化できます。

  • 未実装のブラウザベンダから新たな関心が寄せられているため、それらのブラウザを元に戻す可能性があります。
  • (クロムベースの)ブラウザを実装する市場の浸透率は高い
  • Google(Chromiumの主要な寄稿者)は、APIの提供終了日を明らかにしていません。

「いくつかのケース」があなた自身のものを含むかどうかは、あなたが決めることです。

* BakedGoodsは、この男以外ではここで管理されていません。)

3
Kevin

このスレッドは、バイナリファイルを生成する方法と指定されたファイルをダウンロードするためのプロンプトをすべてサーバーなしのクライアントコードで作成する方法を理解するのに非常に貴重でした。

私の最初のステップは、保存していたデータからバイナリBLOBを生成することでした。単一のバイナリ型に対してこれを行うためのサンプルはたくさんあります。私の場合は、BLOBを作成するための配列として渡すことができる複数の型を持つバイナリ形式があります。

saveAnimation: function() {

    var device = this.Device;
    var maxRow = ChromaAnimation.getMaxRow(device);
    var maxColumn = ChromaAnimation.getMaxColumn(device);
    var frames = this.Frames;
    var frameCount = frames.length;

    var writeArrays = [];


    var writeArray = new Uint32Array(1);
    var version = 1;
    writeArray[0] = version;
    writeArrays.Push(writeArray.buffer);
    //console.log('version:', version);


    var writeArray = new Uint8Array(1);
    var deviceType = this.DeviceType;
    writeArray[0] = deviceType;
    writeArrays.Push(writeArray.buffer);
    //console.log('deviceType:', deviceType);


    var writeArray = new Uint8Array(1);
    writeArray[0] = device;
    writeArrays.Push(writeArray.buffer);
    //console.log('device:', device);


    var writeArray = new Uint32Array(1);
    writeArray[0] = frameCount;
    writeArrays.Push(writeArray.buffer);
    //console.log('frameCount:', frameCount);

    for (var index = 0; index < frameCount; ++index) {

      var frame = frames[index];

      var writeArray = new Float32Array(1);
      var duration = frame.Duration;
      if (duration < 0.033) {
        duration = 0.033;
      }
      writeArray[0] = duration;
      writeArrays.Push(writeArray.buffer);

      //console.log('Frame', index, 'duration', duration);

      var writeArray = new Uint32Array(maxRow * maxColumn);
      for (var i = 0; i < maxRow; ++i) {
        for (var j = 0; j < maxColumn; ++j) {
          var color = frame.Colors[i][j];
          writeArray[i * maxColumn + j] = color;
        }
      }
      writeArrays.Push(writeArray.buffer);
    }

    var blob = new Blob(writeArrays, {type: 'application/octet-stream'});

    return blob;
}

次のステップは、事前定義された名前でこのBLOBをダウンロードするようにユーザーにプロンプ​​トを出すことです。

必要なのはHTML 5に追加した名前付きリンクだけで、これを使用して初期ファイル名の名前を変更できます。リンクは表示する必要がないので、非表示にしました。

<a id="lnkDownload" style="display: none" download="client.chroma" href="" target="_blank"></a>

最後のステップは、ファイルをダウンロードするようにユーザーに促すことです。

var data = animation.saveAnimation();
var uriContent = URL.createObjectURL(data);
var lnkDownload = document.getElementById('lnkDownload');
lnkDownload.download = 'theDefaultFileName.extension';
lnkDownload.href = uriContent;
lnkDownload.click();
1
tgraupmann

これはZipとしてファイルをエクスポートするためのチュートリアルです:

始める前に、ファイルを保存するためのライブラリがあります、ライブラリの名前はfileSaver.jsです、あなたはここでこのライブラリを見つけることができます。始めましょう、今、必要なライブラリを含めます。

<script src="https://cdnjs.cloudflare.com/ajax/libs/jszip/3.1.4/jszip.min.js"  type="text/javascript"></script>
<script type="text/javascript" src="https://fastcdn.org/FileSaver.js/1.1.20151003/FileSaver.js" ></script>

このコードをコピーすると、このコードはHello Worldという内容のファイルhello.txtを含むZipファイルをダウンロードします。すべてうまくいけば、これはファイルをダウンロードするでしょう。

<script type="text/javascript">
    var Zip = new JSZip();
    Zip.file("Hello.txt", "Hello World\n");
    Zip.generateAsync({type:"blob"})
    .then(function(content) {
        // see FileSaver.js
        saveAs(content, "file.Zip");
    });
</script>

これはfile.Zipというファイルをダウンロードします。あなたはここでもっと読むことができます: http://www.wapgee.com/story/248/guide-to-create-Zip-files-using-javascript-by-using-jszip-library

1
Ilyas karim

やってみる

let a = document.createElement('a');
a.href = "data:application/octet-stream,"+encodeURIComponent('"My DATA"');
a.download = 'myFile.json';
a.click();
0