web-dev-qa-db-ja.com

ajaxのサーバー応答からExcelファイル(.xlsx)を取得する

Excelファイルを取得し、そのファイルで(成功したajaxメソッドで)応答を取得した後、ブラウザーでダウンロードウィンドウを開くときに問題が発生しました。適切なContent-Type and Content-Disposition headers、jsでBlobを使用しようとしましたが、必要なものを達成できませんでした-単純なファイルのダウンロード。
Ajaxのいくつかのバージョンを達成しましたが、そのうちの1つを以下に示します。 Excelファイルを返すajaxを開発しましたが、Excelファイルが破損しているため(.xlsx拡張子にもかかわらず)正しく開くことができませんでした。

たぶん、問題はBlobコンストラクターで使用される不適切なデータ型にありますか?

成功メソッドの引数の「データ」の代わりに「xhr.response」を使用しようとしましたが、うまくいきません。 Chrome=で開発者ツールの応答ヘッダーをチェックし、適切に設定されています。
重要なこと-サーバー側で作成されたすべてのExcelブックは、データがajaxポストではなくURLで送信された以前のバージョンで機能したため、正しいです。

以下のJava/Springサーバー側のコントローラーメソッド:

response.reset();
response.setContentType("application/vnd.ms-Excel");
response.addHeader("Content-Disposition","attachment;filename=\"" + className + " " +  title + ".xlsx\"");
    try (ServletOutputStream output = response.getOutputStream()){
        workbook.write(output);
        output.flush();
    } catch (Exception e) {
        throw new RuntimeException(e);
    }

ファイルをダウンロードしてダウンロードウィンドウを開くMy Ajax:

$.ajax({
    url: myUrl,
    type: 'POST',
    data: myData,
    success: function(data, status, xhr) {
        var contentType = 'application/vnd.ms-Excel';

        var filename = "";
        var disposition = xhr.getResponseHeader('Content-Disposition');
        if (disposition && disposition.indexOf('attachment') !== -1) {
            var filenameRegex = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/;
            var matches = filenameRegex.exec(disposition);
            if (matches != null && matches[1]) filename = matches[1].replace(/['"]/g, '');
        }
        console.log("FILENAME: " + filename);

        try {
            var blob = new Blob([data], { type: contentType });

            var downloadUrl = URL.createObjectURL(blob);
            var a = document.createElement("a");
            a.href = downloadUrl;
            a.download = filename;
            document.body.appendChild(a);
            a.click();

        } catch (exc) {
            console.log("Save Blob method failed with the following exception.");
            console.log(exc);
        }
5
KamilosD

JQueryが応答からのバイナリデータの処理に問題を抱えているようです。単純にXMLHttpRequestを使用し、すべてのデータをURLに追加します。

var request = new XMLHttpRequest();
request.open('POST', url, true);
request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');
request.responseType = 'blob';

request.onload = function(e) {
    if (this.status === 200) {
        var blob = this.response;
        if(window.navigator.msSaveOrOpenBlob) {
            window.navigator.msSaveBlob(blob, fileName);
        }
        else{
            var downloadLink = window.document.createElement('a');
            var contentTypeHeader = request.getResponseHeader("Content-Type");
            downloadLink.href = window.URL.createObjectURL(new Blob([blob], { type: contentTypeHeader }));
            downloadLink.download = fileName;
            document.body.appendChild(downloadLink);
            downloadLink.click();
            document.body.removeChild(downloadLink);
           }
       }
   };
   request.send();
11
KamilosD

私たちは最近、まったく同じ問題を抱えていました。私たちにとっては、responseType: 'arraybuffer'ajaxパラメーターに。そして、lib https://github.com/eligrey/FileSaver.js/このツールもメモリを無効にするため、手動でリンクをクリックする代わりに。

0