web-dev-qa-db-ja.com

サーバーで生成されたZipファイルのクライアントダウンロード

誰かが「重複する」と言う前に、私は人々が知っていることを確認したいだけです。

1)angularとphpを使用します。ここで何が起こっているのかわかりません(PHPはわかりません): Zipファイルをダウンロードし、angularメソッド

2)この答えで何もできない: angularを使用してZipファイルをダウンロードする方法

3)この人はすでにダウンロードできますが、これは私が理解しようとしているポイントを超えています: 外部のZipファイルをダウンロードangularボタンアクションでトリガー

4)これに対する答えはありません: nodejsのサーバーから.Zipファイルをダウンロード

5)これが何の言語かわからない: https://stackoverflow.com/questions/35596764/Zip-file-download-using-angularjs-directive

それらの質問を考慮して、これがまだ重複している場合は、お詫び申し上げます。ここに、まだ、この質問の別のバージョンがあります。

My angular 1.5.Xクライアントは、タイトルのリストを提供し、それぞれに関連ファイルがあります。MyNode 4.X/Express 4.Xサーバーそのリストを取得し、ファイルの場所を取得し、npmからのexpress-Zipを使用してZipファイルを作成し、そのファイルを応答でストリーミングします。次に、クライアントにブラウザーの「ファイルのダウンロード」オプションを開始してもらいます。

これが私のクライアントコードです(Angular 1.5.X):

function bulkdownload(titles){
    titles = titles || [];
    if ( titles.length > 0 ) {
        $http.get('/query/bulkdownload',{
            params:{titles:titles},
            responseType:'arraybuffer'
        })
        .then(successCb,errorCb)
        .catch(exceptionCb);
    }

    function successCb(response){
        // This is the part I believe I cannot get to work, my code snippet is below
    };

    function errorCb(error){
            alert('Error: ' + JSON.stringify(error));
    };

    function exceptionCb(ex){
            alert('Exception: ' + JSON.stringify(ex));
    };
};

express-Ziphttps://www.npmjs.com/package/express-Zip を含むノード(4.X)コード:

router.get('/bulkdownload',function(req,resp){
    var titles = req.query.titles || [];

    if ( titles.length > 0 ){
        utils.getFileLocations(titles).
        then(function(files){
            let filename = 'zipfile.Zip';

            // .Zip sets Content-Type and Content-disposition
            resp.Zip(files,filename,console.log);
        },
        _errorCb)
    }
});

これが私のクライアントコード(Angular 1.5.X)での私のsuccessCbです。

function successCb(response){
    var URL = $window.URL || $window.webkitURL || $window.mozURL || $window.msURL;
    if ( URL ) {
        var blob = new Blob([response.data],{type:'application/Zip'});
        var url = URL.createObjectURL(blob);
        $window.open(url);
    }
};

「ブロブ」の部分は問題なく動作するようです。 IEのデバッガーで確認すると、オクテット情報のファイルストリームのように見えます。今、私はそのblobをいくつかのHTML5ディレクティブに入れて、ブラウザーから「名前を付けて保存」を開始する必要があると思います。多分?そうでないかもしれない?

ユーザーの90%以上がIE11を使用しているため、PhantomJS(Karma)とIEですべてのangularをテストします。コードを実行すると、古い「アクセスが拒否されました」エラーが表示されます警告ウィンドウで:

Exception: {"description":"Access is denied...<stack trace>}

提案、説明、回答などは大歓迎です!

9
westandy

bulkdownloadメソッドを更新して、$window.open(...)の代わりに$http.get(...)を使用します。

function bulkdownload(titles){
    titles = titles || [];
    if ( titles.length > 0 ) {
        var url = '/query/bulkdownload?';
        var len = titles.length;
        for ( var ii = 0; ii < len; ii++ ) {
            url = url + 'titles=' + titles[ii];
            if ( ii < len-1 ) {
                url = url + '&';
            }
        }
        $window.open(url);
    }
};

IE11でのみテストしました。

2
westandy
var Zip_file_path = "" //put inside "" your path with file.Zip
var Zip_file_name = "" //put inside "" file name or something
var a = document.createElement("a");
document.body.appendChild(a);
a.style = "display: none";
a.href = Zip_file_path;
a.download = Zip_file_name;
a.click();
document.body.removeChild(a);
5
atom

これを使用してください:

var url="YOUR Zip URL HERE";
window.open(url, '_blank');
3
Chinmay235

この回答 に示されているように、以下のJavascript関数を使用して、byte[] arrayコンテンツを正常にダウンロードできるようになりました。

バイト配列ストリーム(文字列のタイプ)をblobオブジェクトに変換する関数:

var b64toBlob = function(b64Data, contentType, sliceSize) {
      contentType = contentType || '';
      sliceSize = sliceSize || 512;

      var byteCharacters = atob(b64Data);
      var byteArrays = [];

      for (var offset = 0; offset < byteCharacters.length; offset += sliceSize) {
        var slice = byteCharacters.slice(offset, offset + sliceSize);

        var byteNumbers = new Array(slice.length);
        for (var i = 0; i < slice.length; i++) {
          byteNumbers[i] = slice.charCodeAt(i);
        }

        var byteArray = new Uint8Array(byteNumbers);

        byteArrays.Push(byteArray);
      }

      var blob = new Blob(byteArrays, {type: contentType});
      return blob;
};

これは私がこの関数を呼び出して FileSaver.js でblobオブジェクトを保存する方法です(Angular.js $http.getを介してデータを取得する):

    $http.get("your/api/uri").success(function(data, status, headers, config) {
        //Here, data is type of string
        var blob = b64toBlob(data, 'application/Zip');
        var fileName = "download.Zip";
        saveAs(blob, fileName);
    });

注:私はbyte[] array(Java-Server-Side)を次のように送信しています:

byte[] myByteArray = /*generate your Zip file and convert into byte array*/ new byte[]();
return new ResponseEntity<byte[]>(myByteArray , headers, HttpStatus.OK);
0