Salut les gars,
J'ai vu que certains d'entre nous essayaient de servir un fichier à partir d'une requête ajax. Après quelques recherches, je n'ai pas trouvé de solution claire pour le faire. En peaufinant certains d'entre eux, j'ai exporté avec succès des données csv et xls à partir d'une requête Ajax. Le fait est que la manipulation est différente si le type de fichier est xls, à cause de l'encodage, il y a donc un peu de réglages.
Les données proviennent d'une requête Eloquent typique, convertie en 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 : ce n'est pas un problème
Merci beaucoup cela fonctionne bien pour CSV mais pas xls,
J'avais besoin de retourner un xlsx d'ajax, alors j'ai encore un peu modifié et voici ce que j'obtiens :
PHP
$data est une requête Eloquent convertie en 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);
}
});
Merci!!
Je reçois l'erreur "Classe 'Excel' introuvable". Pourriez-vous m'aider s'il vous plaît ?
@randomhoodie une source sur la façon dont vous avez trouvé cette solution ?
@eldyvoon comme je l'ai dit, "j'ai modifié" la réponse d'origine, enlevez ce dont je n'avais pas besoin, rendez-le compact et duckduckgo (moteur de recherche) pour le type mime de l'extension ms office xlsx, je n'étais pas sûr que ce soit va fonctionner jusqu'à ce que je l'aie essayé, mais je l'ai essayé avant de poster, et comme cela a fonctionné, je l'ai posté, au cas où quelqu'un le trouverait utile.
J'ai trouvé qu'aucun javascript ni ajax n'est nécessaire. J'ai une page Web avec des liens pour télécharger un tas de fichiers csv/xls/xlsx différents et je ne veux pas du tout que la page soit actualisée. Tout ce que j'ai fait, c'est de connecter un lien à une action qui a renvoyé ce qui suit ...
fonction publique getSpreadsheet() {
$items = Item::all();
Excel::create('items', function($excel) use($items) {
$excel->sheet('ExportFile', function($sheet) use($items) {
$sheet->fromArray($items);
});
})->export('xls');
}
Merveilleux!!!!
Merci @randomhoodie !
Pour le package 3.x, je mettrais à jour votre PHP avec quelque chose comme ceci, selon le guide de mise à niveau :
$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);
Merci @kynetiv , j'utilise la version 3.x, mais j'avais besoin de mettre une extension comme : filename.xlsx
Si vous rencontrez toujours ce problème en 2020. Notez que la version 3.x de Laravel excel a changé alors voici la solution
Exemple:
$exports = new ReportsExporter($data, $columns);
Excel::store($exports , 'filename.xlsx', 'custom_disk_location');
définissez votre emplacement de disque personnalisé dans le système de fichiers de configuration comme celui-ci
'custom_disk_location' => [
'driver' => 'local',
'root' => public_path('files'),
],
...
cela garantira que le fichier excel n'est pas enregistré dans le stockage/l'application
mais l'enregistrera dans le chemin public/files sur votre serveur
retour à votre javascript, téléchargez le fichier comme ceci
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);
}
appelez la fonction de téléchargement en passant le nom de fichier et le chemin
download("filename.xlsx", location.origin+"files/filename.xlsx");
après le téléchargement n'oubliez pas de revenir sur le serveur et de supprimer celui stocké sur le serveur comme ceci
unlink("fichiers/nom_fichier.xlsx");
J'espère que cela aidera tous ceux qui ont du mal à télécharger laravel-excel via ajax ou javascript.
C'est une meilleure option car elle vous donne plus de flexibilité pour personnaliser votre expérience utilisateur et
donnez-leur des commentaires sur l'état du téléchargement et nommez votre fichier comme vous le souhaitez.
J'avais besoin de retourner un xlsx d'ajax, alors j'ai encore un peu modifié et voici ce que j'obtiens :
PHP
$data est une requête Eloquent convertie en 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); } });
J'avais besoin de retourner un xlsx d'ajax, alors j'ai encore un peu modifié et voici ce que j'obtiens :
PHP
$data est une requête Eloquent convertie en 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); } });
si bon
Commentaire le plus utile
J'avais besoin de retourner un xlsx d'ajax, alors j'ai encore un peu modifié et voici ce que j'obtiens :
PHP
$data est une requête Eloquent convertie en Array.
js