I am trying to zip a bunch of PDFs together and download in the browser, at the moment the PDF files are zipped and downloaded to the folder the PDFs are stored in, not via the users browser and into their download folder, I have a similar (and much simpler) function which downloads a single PDF so feel like I'm missing something fairly obvious here..
$id is a comma seperated list of filenames, this is then split into an array for looping through and adding to zip file. this bit works, thinking it may be a header issue or with the response.
Any help much appreciated.
public function downloadMultiple($id) {
$id_array = explode(',', $id);
$public_dir = storage_path();
$zipFileName = time().'.zip';
$zip = new ZipArchive;
if ($zip->open($public_dir . '/' . $zipFileName, ZipArchive::CREATE) === TRUE) {
foreach($id_array as $file) {
$file_path = storage_path($file).".pdf";
if (file_exists($file_path)) {
$zip->addFile($file_path,$file.".pdf");
}
}
if ($zip->close()) {
$filetopath = $public_dir.'/'.$zipFileName;
$headers = [
'Cache-control: maxage=1',
'Pragma: no-cache',
'Expires: 0',
'Content-Type : application/octet-stream',
'Content-Transfer-Encoding: binary',
'Content-Type: application/force-download',
'Content-Disposition: attachment; filename='.time().'.zip',
"Content-length: " . filesize($filetopath)
];
if (file_exists($filetopath)) {
$response = response()->download($filetopath, $zipFileName, $headers);
//$response->deleteFileAfterSend(true);
} else {
return ['status'=>'zip file does not exist'];
}
} else {
return ['status'=>'zip file could not close'];
}
} else {
return ['status'=>'Could not create new zip'];
}
}
Update: Definitely gets to the return and does create the file, it just doesn't seem to download for the user, the below is what is brought back in the inspector so clearly something not working as expected
may be worth while mentioning the code which is sent to the controller
let xhr = new XMLHttpRequest(), self = this;
xhr.open('GET', window.location.origin+'/download-multiple/' + this.selected);
xhr.onload = function () {
};
xhr.send();
Assuming you're getting to that part of the controller method, I believe the problem is that you're not returning your response:
if (file_exists($filetopath)) {
// $response = response()->download($filetopath, $zipFileName, $headers);
// $response->deleteFileAfterSend(true);
return response()->download($filetopath, $zipFileName, $headers)->deleteFileAfterSend(true);
} else {
return ['status'=>'zip file does not exist'];
}
EDIT: The problem is you're trying to load the file via AJAX, which you can't do the way that you're trying to do it (see here for examples on how to do it). Change your javascript to:
let xhr = new XMLHttpRequest(), self = this;
window.location = window.location.origin+'/download-multiple/' + this.selected