Laravel-excel: 方法:ajaxのみを使用してcsv / xlsファイルを保存する

作成日 2016年07月14日  ·  12コメント  ·  ソース: Maatwebsite/Laravel-Excel

こんにちは、みんな、

私たちの何人かがajaxリクエストからファイルを提供しようとしているのを見てきました。 いくつかの調査の後、私はそれを行うための明確な解決策を見つけられませんでした。 それらのいくつかを微調整して、Ajaxリクエストからcsvおよびxlsデータを正常にエクスポートしました。 重要なのは、ファイルタイプがxlsの場合、エンコーディングのために操作が異なるため、少し調整が必要です。

データは、典型的なEloquentクエリから取得され、配列に変換されます。

PHP

if(!empty(Input::get('exportType'))) { //i use a custom get parameter here
            $dd = Excel::create('testFileName', function($excel) use ($data) {
                $excel->sheet('testSheetName', function($sheet) use ($data) {
                    $sheet->fromArray($data->get()->toArray());
                });
                $excel->setTitle($filename);
                $excel->setLastModifiedBy(Carbon::now()->toDayDateTimeString()); //updated has Carbon::now() only now throw exception on vendor/phpoffice/phpexcel/Classes/PHPExcel/Writer/Excel5.php l847 strlen()
            });

            //tweak for serving XLS file from ajax (or go trough download() Excel method for csv files)
            if(Input::get('exportType') == 'xls') {
                $dd = $dd->string();
                $response =  array(
                    'filename' => 'testFileName', //as we serve a custom response, HTTP header for filename is not setted by Excel. From the JS, you need to retrieve this value if type is XLS to set filename
                    'file' => "data:application/vnd.ms-excel;base64,".base64_encode($dd)
                );
                return response()->success($response); //do a json encode
            } else {
                //direct use of Excel download method for non-xls files - xls files need special JS treatment
                $dd->download(Input::get('exportType')); //not XLS, so CSV (didnt tried xlsx, pdf is blank but not sure it's related to this)
            }
            die; //prevent malformed binary data stream, not sure if needed
        }

JS

$.ajax({
      cache: false,
      url: url, //GET route 
      responseType: 'ArrayBuffer', //not sure if needed
      data:  exportParam, //exportType parameter here
      success: function (data, textStatus, request) {

//you could need to decode json here, my app do it automaticly, use a try catch cause csv are not jsoned

        //already json decoded? custom return from controller so format is xls
        if(jQuery.isPlainObject(data)) {
          data = data.data; //because my return data have a 'data' parameter with the content
        }

        //V1 - http://stackoverflow.com/questions/35378081/laravel-excel-using-with-ajax-is-not-working-properly
        //+V3 - http://stackoverflow.com/questions/27701981/phpexcel-download-using-ajax-call
        var filename = "";
        var disposition = request.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, '');
        }
        if(!jQuery.isPlainObject(data)) { //is CSV - we use blob
           var type = request.getResponseHeader('Content-Type');
           var blob = new Blob([data], { type: type ,endings:'native'});
           var URL = window.URL || window.webkitURL;
           var downloadUrl = URL.createObjectURL(blob);
        }
        var a = document.createElement("a");
        a.href = jQuery.isPlainObject(data) ? data.file : downloadUrl; 
        a.download = jQuery.isPlainObject(data) ? data.filename : filename;
        document.body.appendChild(a);
        a.click();
        a.remove();
      },
      error: function (ajaxContext) {
        toastr.error('Export error: '+ajaxContext.responseText);
      }
    });

ps:これは問題ではありません

最も参考になるコメント

ajaxからxlsxを返す必要があったので、もう一度少し調整しました。これが最終的な結果です。

PHP
$ dataは、配列に変換されたEloquentクエリです。

$myFile= Excel::create("filename", function($excel) use($data) {
   $excel->setTitle('title');
   $excel->sheet('sheet 1', function($sheet) use($data) {
     $sheet->fromArray($data, null, 'A1', true, true);
   });
});

$myFile = $myFile->string('xlsx'); //change xlsx for the format you want, default is xls
$response =  array(
   'name' => "filename", //no extention needed
   'file' => "data:application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;base64,".base64_encode($myFile) //mime type of used format
);
return response()->json($response);

js

$.ajax({
      cache: false,
      url: url, //GET route 
      data:  params, //your parameters data here
      success: function (response, textStatus, request) {
        var a = document.createElement("a");
        a.href = response.file; 
        a.download = response.name;
        document.body.appendChild(a);
        a.click();
        a.remove();
      },
      error: function (ajaxContext) {
        toastr.error('Export error: '+ajaxContext.responseText);
      }
    });

全てのコメント12件

CSVには適していますが、xlsには適していません。

ajaxからxlsxを返す必要があったので、もう一度少し調整しました。これが最終的な結果です。

PHP
$ dataは、配列に変換されたEloquentクエリです。

$myFile= Excel::create("filename", function($excel) use($data) {
   $excel->setTitle('title');
   $excel->sheet('sheet 1', function($sheet) use($data) {
     $sheet->fromArray($data, null, 'A1', true, true);
   });
});

$myFile = $myFile->string('xlsx'); //change xlsx for the format you want, default is xls
$response =  array(
   'name' => "filename", //no extention needed
   'file' => "data:application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;base64,".base64_encode($myFile) //mime type of used format
);
return response()->json($response);

js

$.ajax({
      cache: false,
      url: url, //GET route 
      data:  params, //your parameters data here
      success: function (response, textStatus, request) {
        var a = document.createElement("a");
        a.href = response.file; 
        a.download = response.name;
        document.body.appendChild(a);
        a.click();
        a.remove();
      },
      error: function (ajaxContext) {
        toastr.error('Export error: '+ajaxContext.responseText);
      }
    });

ありがとう!!

「クラス 'Excel'が見つかりません」というエラーが表示されます。助けてもらえますか?

@randomhoodieどのようにしてそのソリューションを思いついたのですか?

@eldyvoonは、元の回答を「微調整」し、不要なものを取り除き、コンパクトにし、mimeタイプのms office xlsx拡張機能用のduckduckgo(検索エンジン)を使用したかどうかはわかりませんでした。試してみるまでは動作しますが、投稿する前に試してみました。動作したので、誰かが役に立つと思う場合に備えて投稿しました。

javascriptもajaxもまったく必要ないことがわかりました。 さまざまなcsv / xls / xlsxファイルをダウンロードするためのリンクが記載されたWebページがありますが、ページを更新したくありません。 私がしたのは、次を返すアクションへのリンクをフックすることだけでした...

パブリック関数getSpreadsheet(){
$ items = Item :: all();
Excel :: create( 'items'、function($ excel)use($ items){
$ excel-> sheet( 'ExportFile'、function($ sheet)use($ items){
$ sheet-> fromArray($ items);
});
})-> export( 'xls');
}

素晴らしい!!!!

ありがとう@randomhoodie!

3.xパッケージの場合、アップグレードガイドに従ってPHPを次のように更新します。

        $myFile = Excel::raw(new YOUR_Export_Class, \Maatwebsite\Excel\Excel::XLSX);

        $response =  array(
           'name' => "filename", //no extention needed
           'file' => "data:application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;base64,".base64_encode($myFile) //mime type of used format
        );

        return response()->json($response);

@kynetivに感謝します。バージョン3.xを使用していますが、filename.xlsxのような拡張子を付ける必要がありました。

2020年もまだこの問題が発生している場合。LaravelExcelのバージョン3.xが変更されているため、ここに解決策があります。

  1. LaravelExcelオブジェクトと相互作用するコントローラーにAjaxを介してデータを送信します
  2. LaravelExcelオブジェクトにデータをブレードビューに送信させます
  3. ブレードビューをサーバーに保存します
  4. jsを使用してサーバーにファイルをダウンロードします。
    したがって、アイデアは、ブレードビューをExcelとしてエクスポートし、ダウンロードできるディスクの場所に保存することです。
    javascript。

例:

 $exports = new ReportsExporter($data, $columns);
  Excel::store($exports , 'filename.xlsx', 'custom_disk_location');

このように設定ファイルシステムでカスタムディスクの場所を定義します

'custom_disk_location' => [
            'driver' => 'local',
            'root' => public_path('files'),
        ],
...

これにより、Excelファイルがストレージ/アプリに保存されないようになります
ただし、サーバーのpublic / filesパスに保存されます

JavaScriptに戻り、次のようなファイルをダウンロードします

function download(filename, path) {
        let element = document.createElement('a');
        element.setAttribute('href', path);
        element.setAttribute('download', filename);

        element.style.display = 'none';
        document.body.appendChild(element);

        element.click();

        document.body.removeChild(element);
    }

ファイル名とパスを渡してダウンロード関数を呼び出します
download( "filename.xlsx"、location.origin + "files / filename.xlsx");

ダウンロード後、サーバーに戻って、このようにサーバーに保存されているものを削除することを忘れないでください
unlink( "files / filename.xlsx");

これが、ajaxまたはjavascriptを介してlaravel-excelをダウンロードするのが難しいと感じる人に役立つことを願っています。
これは、ユーザーエクスペリエンスをカスタマイズする柔軟性が高くなり、
ダウンロードのステータスや、ファイルに好きな名前を付けることに関して、フィードバックを提供します。

ajaxからxlsxを返す必要があったので、もう一度少し調整しました。これが最終的な結果です。

PHP
$ dataは、配列に変換されたEloquentクエリです。

$myFile= Excel::create("filename", function($excel) use($data) {
   $excel->setTitle('title');
   $excel->sheet('sheet 1', function($sheet) use($data) {
     $sheet->fromArray($data, null, 'A1', true, true);
   });
});

$myFile = $myFile->string('xlsx'); //change xlsx for the format you want, default is xls
$response =  array(
   'name' => "filename", //no extention needed
   'file' => "data:application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;base64,".base64_encode($myFile) //mime type of used format
);
return response()->json($response);

js

$.ajax({
      cache: false,
      url: url, //GET route 
      data:  params, //your parameters data here
      success: function (response, textStatus, request) {
        var a = document.createElement("a");
        a.href = response.file; 
        a.download = response.name;
        document.body.appendChild(a);
        a.click();
        a.remove();
      },
      error: function (ajaxContext) {
        toastr.error('Export error: '+ajaxContext.responseText);
      }
    });

ajaxからxlsxを返す必要があったので、もう一度少し調整しました。これが最終的な結果です。

PHP
$ dataは、配列に変換されたEloquentクエリです。

$myFile= Excel::create("filename", function($excel) use($data) {
   $excel->setTitle('title');
   $excel->sheet('sheet 1', function($sheet) use($data) {
     $sheet->fromArray($data, null, 'A1', true, true);
   });
});

$myFile = $myFile->string('xlsx'); //change xlsx for the format you want, default is xls
$response =  array(
   'name' => "filename", //no extention needed
   'file' => "data:application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;base64,".base64_encode($myFile) //mime type of used format
);
return response()->json($response);

js

$.ajax({
      cache: false,
      url: url, //GET route 
      data:  params, //your parameters data here
      success: function (response, textStatus, request) {
        var a = document.createElement("a");
        a.href = response.file; 
        a.download = response.name;
        document.body.appendChild(a);
        a.click();
        a.remove();
      },
      error: function (ajaxContext) {
        toastr.error('Export error: '+ajaxContext.responseText);
      }
    });

とても良い

このページは役に立ちましたか?
0 / 5 - 0 評価