Hola tios,
He visto que algunos de nosotros estamos tratando de servir un archivo desde una solicitud ajax. Después de algunas investigaciones, no encontré ninguna solución clara para hacerlo. Al ajustar algunos de ellos, exporté con éxito datos csv y xls desde una solicitud Ajax. La cuestión es que la manipulación es diferente si el tipo de archivo es xls, debido a la codificación, por lo que hay algunos ajustes.
Los datos provienen de una consulta típica de Eloquent, convertida a 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: esto no es un problema
Muchas gracias, funciona bien para CSV pero no xls,
Necesitaba devolver un xlsx de ajax, así que lo modifiqué un poco nuevamente y esto es lo que termino con:
PHP
$ data es una consulta Eloquent convertida a Array.
$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);
}
});
¡¡Gracias!!
Recibo el error "Clase 'Excel' no encontrada". ¿Podrían ayudarme?
@randomhoodie alguna fuente ¿cómo surgió esa solución?
@eldyvoon, como dije, "modifiqué" la respuesta original, eliminé lo que no necesitaba, lo hice compacto y duckduckgo (motor de búsqueda) para el tipo mime de la extensión ms office xlsx, no estaba seguro de que fuera Funcionará hasta que lo probé, pero lo probé antes de publicarlo, y como funcionó lo publiqué, en caso de que alguien lo encontrara útil.
Descubrí que no se necesita javascript ni ajax en absoluto. Tengo una página web con enlaces para descargar un montón de archivos csv / xls / xlsx diferentes y no quiero que la página se actualice en absoluto. Todo lo que hice fue conectar un enlace a una acción que devolvió lo siguiente ...
función pública getSpreadsheet () {
$ elementos = Elemento :: todos ();
Excel :: create ('elementos', función ($ excel) use ($ elementos) {
$ excel-> hoja ('ExportFile', función ($ hoja) use ($ elementos) {
$ hoja-> fromArray ($ elementos);
});
}) -> exportar ('xls');
}
Maravilloso !!!!
¡Gracias @randomhoodie!
Para el paquete 3.x, actualizaría su PHP con algo como esto, según la guía de actualización :
$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);
Gracias @kynetiv , uso la versión 3.x, pero necesitaba poner una extensión como: filename.xlsx
Si todavía tiene este problema en 2020, tenga en cuenta que la versión 3.x de Laravel Excel ha cambiado, así que aquí está la solución
Ejemplo:
$exports = new ReportsExporter($data, $columns);
Excel::store($exports , 'filename.xlsx', 'custom_disk_location');
defina su ubicación de disco personalizada en el sistema de archivos de configuración de esta manera
'custom_disk_location' => [
'driver' => 'local',
'root' => public_path('files'),
],
...
esto asegurará que el archivo de Excel no se guarde en el almacenamiento / aplicación
pero lo guardará en la ruta pública / archivos en su servidor
de vuelta a su javascript, descargue el archivo como este
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);
}
llamar a la función de descarga pasando el nombre del archivo y la ruta
descargar ("nombre de archivo.xlsx", ubicación.origen + "archivos / nombre de archivo.xlsx");
después de la descarga recuerde volver al servidor y eliminar el almacenado en el servidor de esta manera
desvincular ("archivos / nombrearchivo.xlsx");
Espero que esto ayude a cualquiera que tenga dificultades para descargar laravel-excel a través de ajax o javascript.
Esta es una mejor opción, ya que le brinda más flexibilidad para personalizar su experiencia de usuario y
déles su opinión sobre el estado de la descarga y asigne un nombre a su archivo como desee.
Necesitaba devolver un xlsx de ajax, así que lo modifiqué un poco nuevamente y esto es lo que termino con:
PHP
$ data es una consulta Eloquent convertida a Array.$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); } });
Necesitaba devolver un xlsx de ajax, así que lo modifiqué un poco nuevamente y esto es lo que termino con:
PHP
$ data es una consulta Eloquent convertida a Array.$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); } });
tan bueno
Comentario más útil
Necesitaba devolver un xlsx de ajax, así que lo modifiqué un poco nuevamente y esto es lo que termino con:
PHP
$ data es una consulta Eloquent convertida a Array.
js