PHP can't access newly created zip file - php

Im using Laravel 5.2 and Zipper to create ZIP archive in a fly and download it by user. I think this problem is generall not strictly related to Laravel or Zipper. Steps:
User click link download_all.
First php script create archive.
Next the same script push created file to force user download.
Everything sounds normal but I have strange behaviour that after zip archive is created (point 2) php/server cant see this newly created file.
Both filesize and file_exists on $filePath return false but file exist. I cant read file why?
When I redirect user to $filePath (instead of reading it and pushing to download) everything is okay and user get file. But why I cant access newly creatd file during "script lifetime"? $paths are correct.
Tested on Windows 7 and Unix.
Any idea?
code:
public function downloadAll($id)
{
$sourceFilesDir = 'upload/source/' . $id;
$zipPath = 'upload/source-zip/' . date('Y-m-d-H-i-s') . '.zip';
Zipper::make($zipPath)->add($sourceFilesDir);
$fullPath = public_path($zipPath);
// works
// return response()->redirectTo($zipPath);
$headers = [
'Content-Type: application/zip',
'Content-Transfer-Encoding: Binary',
'Content-Length: ' . filesize($fullPath),
];
// dont works, cant see file
return response()->download($fullPath, basename($zipPath), $headers);
}

Soved by #Holger.
Zipper should be closed to save file.
Proper code:
Zipper::make($zipPath)->add($sourceFilesDir)->close();
->close()
Unfortunately in Zipper docs this is not clearly mentioned.

Related

(Laravel/PHP) How to save file in memory or delete file before return without causing error?

(It's API only) I'm using JasperPHP to generate reports, the user can choose the extension (xls or pdf). After I process the data, then I save the file/report locally, it's in "storage/app/jasper/example1234.pdf".
So at the end of the function I do this:
// more code
$file = $path . $filename . '.' . $extension; // file path
// more code
return response()->file($file);
And it works, I can get the file using ReactJS. OK! But I wanted to delete the file before the "return", but if I do that the file will not be read on the "return". That's why I wanted to save it in a variable/memory first, delete the file locally and then return.
Note I tried to get the file using several methods, such as "Storage::get()", but they all generate errors on "return", stating that "string file" is expected but "resource" was given.
Response facade has deleteFileAfterSend() method. You can use it like the following:
return response()->file($file)->deleteFileAfterSend();

is it possible to send a zipped folder from server (php) to front end (angular) ? or is there another way to do it

I am using drupal as a back end.
in drupal I get some .pdf files. and then zip them using drupal zip archive. then saving this archive in my server tmp folder, i get the tmp folder using php sys_get_temp_dir()
now...
what should i return to the front end (Angular) so that the user can download this folder..
this is an example code i used for zipping:
$nodesIds = [1024, 1023, 1022]; // those are just some example ids, i get the real ids from the front end post request.
$zipName = $this->generateUniqueName();
$zip = new \ZipArchive;if(!$zip->open(sys_get_temp_dir() . '/' . $zipName, constant("ZipArchive::CREATE"))) {
return new JsonResponse('could not open zip');
}
foreach ($nodesIds as $id) {
$node = \Drupal\node\Entity\Node::load($id);
$uri = $node->filed_file->entity->getFileUri();
$name = $node->field_file->entity->id() . '_'. $node->field_file->entity->getFilename();
$url = $file_system->realpath($uri);
$zip->addFile($url, $name);
}
$zip->close();
i tried returning a link to the zipped folder in the server:
return new JsonResponse(sys_get_temp_dir() . '/' . $zipName);
but i dont know what to do with that from angular.
Also tried to return a stream using symfony:
$stream = new Stream(sys_get_temp_dir() . '/' . $zipName);
$response = new BinaryFileResponse($stream);
a stream and not a file because the user chooses which files to zip.. so they can choose as much as they want.. it might get to even a 100 .pdf files ..
every thing works fine and i get the zipped folder in tmp.. but now what ?
I want to download this zipped folder to the user browser..
but I do not know how!. should I return the zipped folder, then in angular use it as a blob or somehow deal with it and serve it to the user,,
or maybe the right way is to send back the link to its location in the tmp folder,, and in angular i only access that location and somehow get the folder (i dont know if this is even possible due to permissions and security), or is there another better way that I do not know about.
thank you very much.

How to delete laravel delete file after extract?

I am using Zipper to extract uploaded zip file and delete the file after extract.
So I upload and extract like this:
$f = $request['file']->move(public_path($directory), $fullFileName);
\Zipper::make($f)->extractTo(public_path($directory) . $fileName);
and it works great. I've tried to delete the file using these ways.
1 - Storage::disk('products')->delete($fullFileName);
2 - File::delete(public_path($directory) . $fullFileName);
3 - $del = unlink(public_path($directory) . $fullFileName);
but in all actions get resource temporarily unavailable error.
I found this error is because of the zipper (simple files and directories works).
so my question is, How can I delete upload zip file after extract, using a zipper?
Any idea would be great.
thanks in advance.
You need to call $zipper->close(); after you extract it, so if you do something like this it should work:
$zipper = new \Chumper\Zipper\Zipper;
$zipper->make($f)->extractTo(public_path($directory) . $fileName);
$zipper->close();
unlink(public_path($directory) . $fullFileName);
If you do not close the zipper it will not write the result to the disk and keep the original file locked. See the documentation.
$zip = new Zipper;
$zip->make($pathZipFile)->extractTo($destinationPath);
$zip->close(); // important
unlink($pathZipFile); // delete Zip file after

How to get name of stored files in public - laravel 5

When i upload my files to the server, it works fine and displays in my public folder as img/php786W. I am currently trying to retrieve my folder but i get file not found on server.
In my controller, $filename is returning the original name of the file on the server. So it does not match to be found although it is the same file.
How can i get this done? I tried to use hashName() but that won't work
Controller
$file_path = public_path() . '/img/'. $filename;
if (file_exists($file_path->hashName()))
{
return Response::download($file_path, $filename, [
'Content-Length: '. filesize($file_path)
]);
}
else
{
// Error
}
Use
return response()->download($pathToFile);
If this does not work you have either permissions problem, or the file simply does not exist
See docs

Laravel Zipper delete files after zipping

I am using a Zipper package for making zip files out of API fetched PDF's. Zipping works fine but I would like to delete PDF files that were zipped.
$pdf_summary_filename = public_path() . $path . uniqid() . '_summary.pdf';
PDF::loadView('pdf.summary', $pdf_data)->save($pdf_summary_filename);
$zipper->make($zip_filename)->add($pdf_summary_filename);
File::cleanDirectory(public_path() . '/user_downloads');
I am using this code, however, I think that cleanDirectory() gets called before the zipping finishes, and I see no zip generated. If I comment out the last line, I get both the zip file as well as PDF's in /user_downloads.
How can I wait for the zipper to finish zipping?
UPDATE: You can try below code:
$flgFile = $zipper->make($zip_filename)->add($pdf_summary_filename);
if($flgFile){
File::cleanDirectory(public_path() . '/user_downloads');
}
This may help you better!

Categories