Laravel-excel: Gewusst wie: Speichern von csv/xls-Dateien nur mit Ajax

Erstellt am 14. Juli 2016  ·  12Kommentare  ·  Quelle: Maatwebsite/Laravel-Excel

Hallo Leute,

Ich habe gesehen, dass einige von uns versuchen, eine Datei aus einer Ajax-Anfrage bereitzustellen. Nach einiger Recherche habe ich keine eindeutige Lösung dafür gefunden. Ich habe einige davon optimiert und erfolgreich CSV- und XLS-Daten aus einer Ajax-Anfrage exportiert. Die Sache ist, dass die Manipulation aufgrund der Codierung anders ist, wenn der Dateityp xls ist, also gibt es ein paar Optimierungen.

Die Daten stammen aus einer typischen Eloquent-Abfrage, konvertiert in Array:

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: das ist kein problem

Hilfreichster Kommentar

Ich musste eine xlsx von ajax zurückgeben, also habe ich noch einmal ein wenig optimiert und das habe ich am Ende:

PHP
$data ist eine in Array konvertierte Eloquent-Abfrage.

$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);
      }
    });

Alle 12 Kommentare

Vielen Dank, es funktioniert gut für CSV, aber nicht für xls.

Ich musste eine xlsx von ajax zurückgeben, also habe ich noch einmal ein wenig optimiert und das habe ich am Ende:

PHP
$data ist eine in Array konvertierte Eloquent-Abfrage.

$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);
      }
    });

Danke!!

Ich erhalte den Fehler "Klasse 'Excel' nicht gefunden". Können Sie mir bitte helfen?

@randomhoodie eine Quelle, wie Sie zu dieser Lösung gekommen sind?

@eldyvoon wie ich sagte, "ich habe die ursprüngliche Antwort optimiert", nimm weg, was ich nicht brauchte, mach es kompakt und duckduckgo (Suchmaschine) für den Mime-Typ der ms office xlsx-Erweiterung, ich war mir nicht sicher, ob es so war Ich werde funktionieren, bis ich es ausprobiert habe, aber ich habe es vor dem Posten versucht, und da es funktioniert hat, habe ich es gepostet, falls es jemand nützlich finden würde.

Ich fand, dass überhaupt kein Javascript oder Ajax benötigt wird. Ich habe eine Webseite mit Links zum Herunterladen verschiedener csv/xls/xlsx-Dateien und ich möchte nicht, dass die Seite aktualisiert wird. Alles, was ich getan habe, war, einen Link zu einer Aktion zu verbinden, die Folgendes zurückgab ...

öffentliche Funktion getSpreadsheet() {
$items = Item::all();
Excel::create('items', function($excel) use($items) {
$excel->sheet('ExportFile', function($sheet) use($items) {
$sheet->fromArray($items);
});
})->export('xls');
}

Wunder voll!!!!

Danke @randomhoodie!

Für das 3.x-Paket würde ich Ihr PHP mit etwas wie diesem aktualisieren , gemäß der

        $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);

Danke @kynetiv , ich verwende Version 3.x, aber ich musste eine Erweiterung wie:

Wenn Sie dieses Problem im Jahr 2020 immer noch haben. Beachten Sie, dass sich die Version 3.x von Laravel Excel geändert hat. Hier ist die Lösung

  1. Senden Sie Ihre Daten über Ajax an Ihren Controller, der mit dem Laravel Excel-Objekt interagiert
  2. Lassen Sie das Laravel-Excel-Objekt Ihre Daten an eine Blade-Ansicht senden
  3. Speichern Sie die Blade-Ansicht auf dem Server
  4. Verwenden Sie js, um die Datei auf den Server herunterzuladen.
    Die Idee ist also, eine Blade-Ansicht als Excel zu exportieren und auf einem Datenträger zu speichern, von dem Sie sie herunterladen können
    Javascript.

Beispiel:

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

Definieren Sie Ihren benutzerdefinierten Festplattenspeicherort im Konfigurationsdateisystem wie folgt

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

Dadurch wird sichergestellt, dass die Excel-Datei nicht im Speicher / in der App gespeichert wird
speichert es aber im öffentlichen/Dateipfad auf Ihrem Server

zurück zu deinem Javascript, lade die Datei wie folgt herunter

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);
    }

Rufen Sie die Download-Funktion auf, indem Sie den Dateinamen und den Pfad übergeben
download("Dateiname.xlsx", Standort.Ursprung+"Dateien/Dateiname.xlsx");

Denken Sie nach dem Download daran, zum Server zurückzukehren und den auf dem Server gespeicherten zu entfernen
unlink("files/filename.xlsx");

Ich hoffe, dies hilft jedem, der es schwer hat, Laravel-Excel über Ajax oder Javascript herunterzuladen.
Dies ist eine bessere Option, da Sie Ihre Benutzererfahrung flexibler anpassen können und
Geben Sie ihnen Feedback zum Status des Downloads und benennen Sie Ihre Datei nach Ihren Wünschen.

Ich musste eine xlsx von ajax zurückgeben, also habe ich noch einmal ein wenig optimiert und das habe ich am Ende:

PHP
$data ist eine in Array konvertierte Eloquent-Abfrage.

$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);
      }
    });

Ich musste eine xlsx von ajax zurückgeben, also habe ich noch einmal ein wenig optimiert und das habe ich am Ende:

PHP
$data ist eine in Array konvertierte Eloquent-Abfrage.

$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);
      }
    });

so gut

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen