How to save download zip to public folder in laravel? - php

I want to download a folder into ZIP format with my code below.
Actually this work perfectly for download folder to zip only.
But i want the zip file also save to public folder in public/folder.
i use laravel and ziparchive
Please help me
public function downloadzip($id_pra) {
$dcmt = DB::table('document')->select(DB::raw(" max(id) as id"))->where('id_praapplication',$id_pra)->groupBy('type')->pluck('id');
$files = Document::whereIn('id', $dcmt)->get();
$url = url('')."/storage/uploads/file/".$id_pra."/";
# create new zip opbject
$zip = new \ZipArchive();
# create a temp file & open it
$tmp_file = tempnam('.','');
$zip->open($tmp_file, \ZipArchive::CREATE);
# loop through each file
foreach($files as $file){
$url2 = $url.$file->upload;
$url2 = str_replace(' ', '%20', $url2);
if (!function_exists('curl_init')){
die('CURL is not installed!');
}
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url2);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$output = curl_exec($ch);
curl_close($ch);
$download_file = $output;
$type = substr($url2, -5, 5);
#add it to the zip
$zip->addFromString(basename($url.$file->upload.'.'.$type),$download_file);
}
# close zip
$zip->close();
# send the file to the browser as a download
ob_start();
$strFile = file_get_contents($tmp_file);
header('Content-disposition: attachment; filename=DOC-'.$id_pra.'-'.$url.'.zip');
header('Content-type: application/zip');
echo $tmp_file;
while (ob_get_level()) {
ob_end_clean();
}
readfile($tmp_file);
exit;
}

Instead of creating a temp file you can just create the ZIP file directly and later use the Filesystem API to download it.
public function downloadzip($id_pra) {
$dcmt = DB::table('document')->select(DB::raw(" max(id) as id"))->where('id_praapplication',$id_pra)->groupBy('type')->pluck('id');
$files = Document::whereIn('id', $dcmt)->get();
$url = url('')."/storage/uploads/file/".$id_pra."/";
// create new zip object
$zip = new \ZipArchive();
// store the public path
$publicDir = public_path();
// Define the file name. Give it a unique name to avoid overriding.
$zipFileName = 'Documents.zip';
// Create the ZIP file directly inside the desired folder. No need for a temporary file.
if ($zip->open($publicDir . '/folder/' . $zipFileName, \ZipArchive::CREATE) === true) {
// Loop through each file
foreach($files as $file){
$url2 = $url.$file->upload;
$url2 = str_replace(' ', '%20', $url2);
if (!function_exists('curl_init')){
die('CURL is not installed!');
}
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url2);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$output = curl_exec($ch);
curl_close($ch);
$download_file = $output;
$type = substr($url2, -5, 5);
#add it to the zip
$zip->addFromString(basename($url.$file->upload.'.'.$type),$download_file);
}
// close zip
$zip->close();
}
// Download the file using the Filesystem API
$filePath = $publicDir . '/folder/' . $zipFileName;
if (file_exists($filePath)) {
return Storage::download($filePath);
}
}
Note:
I would extract the CURL part to a method fetchFile($url); which returns the downloaded file, but this is out of scope of this question.

Related

how to force zip to dowload without temp file?

i want to make dynamic zip, so when admin click .zip, it will download and zip all files in folder based on user ud
user will have document and store on folder with their id
i.e /public/stroage/file/ID001, so when user click button download it will force to download ID0001.zip
here is my code
$zip = new \ZipArchive();
$uploaddir = public_path().'/temp';
$tmp_file = tempnam($uploaddir,'');
$zip->open($tmp_file, \ZipArchive::CREATE);
// Loop through each file
foreach($files as $file){
$url2 = $url.$file->upload;
$url2 = str_replace(' ', '%20', $url2);
if (!function_exists('curl_init')){
die('CURL is not installed!');
}
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url2);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$output = curl_exec($ch);
curl_close($ch);
$download_file = $output;
$type = substr($url2, -5, 5);
#add it to the zip
$zip->addFromString(basename($url.$file->upload.'.'.$type),$download_file);
}
// close zip
$zip->close();
// Set Time Download
date_default_timezone_set("Asia/Kuala_Lumpur");
$time_name = date('Ymd');
$time_download = date('Y-m-d H:i:s');
$log_download = new Log_download;
$user = Auth::user();
$id_user = $user->id;
$log_download->id_praapplication = $id_pra;
$log_download->id_user = $id_user;
$log_download->Activity = 'Download ZIP File';
$log_download->type = 'Zip Archive';
$log_download->downloaded_at = $time_download;
$log_download->save();
# send the file to the browser as a download
ob_start();
$strFile = file_get_contents($tmp_file);
header('Content-disposition: attachment; filename=DOC-'.$id_pra.'-'.'.zip');
header('Content-type: application/zip');
echo $tmp_file;
while (ob_get_level()) {
ob_end_clean();
}
readfile($tmp_file);
//$filetopath=$public_dir.'/'.$zipFileName;
//$filetopath = public_path().'/storage/uploads/file/'. $id_pra.'/'.$zipFileName;
// Create Download Response
// if(file_exists($filetopath)){
// return response()->download($filetopath,$zipFileName,$headers);
//}
exit;
actually this code work. but every utton to dowload zip i clicked, will create a temporary file inside folder /public.
how to download zip without creating temp file or can i make a folder like /public/tmp and save all temp zip to that folder?
You should be able to do $zip->open('php://output', \ZipArchive::CREATE);. Complete code:
header('Content-disposition: attachment; filename=DOC-'.$id_pra.'-'.'.zip');
header('Content-type: application/zip');
$zip = new \ZipArchive();
$zip->open('php://output', \ZipArchive::CREATE);
// Loop through each file
foreach($files as $file){
$url2 = $url.$file->upload;
$url2 = str_replace(' ', '%20', $url2);
if (!function_exists('curl_init')){
die('CURL is not installed!');
}
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url2);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$output = curl_exec($ch);
curl_close($ch);
$download_file = $output;
$type = substr($url2, -5, 5);
#add it to the zip
$zip->addFromString(basename($url.$file->upload.'.'.$type),$download_file);
}
// close zip
$zip->close();
// Set Time Download
date_default_timezone_set("Asia/Kuala_Lumpur");
$time_name = date('Ymd');
$time_download = date('Y-m-d H:i:s');
$log_download = new Log_download;
$user = Auth::user();
$id_user = $user->id;
$log_download->id_praapplication = $id_pra;
$log_download->id_user = $id_user;
$log_download->Activity = 'Download ZIP File';
$log_download->type = 'Zip Archive';
$log_download->downloaded_at = $time_download;
$log_download->save();
exit;
However, the zip filesize should not exceed the PHP max memory limit. If it does, you'll end up with corrupted zip files.

Save image from PHP URL - returns empty image

I'm working on a small project where I read data from electronic identity cards.
It might be worth mentioning I'm using the LightOpenID PHP library to get $attributes[''] with all the data from the eID.
Now I'm stuck trying to save an image which is displayed on http://my-url.com/photo.php
photo.php contains:
<?php
session_start();
$photo = $_SESSION['photo'];
header('Content-Type: image/jpeg');
echo($photo);
The variable $photo contains $_SESSION['photo'] which comes from index.php:
function base64url_decode($base64url) {
$base64 = strtr($base64url, '-_', '+/');
$plainText = base64_decode($base64);
return ($plainText);
}
$encodedPhoto = $attributes['eid/photo'];
$photo = base64url_decode($encodedPhoto);
$_SESSION['photo'] = $photo;
The images are both perfectly visible on index.php (<?php echo '<img src="photo.php"/>'; ?>) as well as on photo.php.
I've read up on a few similar topics and tried the following methods:
cURL
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'http://my-url.com/photo.php');
$fp = fopen('./photo/' . $filename . '.jpg', 'wb');
curl_setopt($ch, CURLOPT_FILE, $fp);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_exec($ch); curl_close($ch);
fclose($fp);
File_put_contents
$input = "my-url.com/photo.php";
$output = './photo/' . $filename . '.jpg';
file_put_contents($output, file_get_contents($input));
copy
Even tried a basic copy:
copy( "http://my-url/photo.php", './photo/' . $filename . '.jpg');
All 3 methods create an empty .jpg file in the directory I want them too.
Let me know if I need to provide any extra code.
Hope there's someone who can point out my mistakes
Finally found a solution.
I decode the base64url only once with:
function base64url_decodeOnce($base64url){
$base64 = strtr($base64url, '-_', '+/');
return ($base64);
}
that way I can use the $base64 output for:
$data = 'data:image/jpeg;base64,' . $base64data .'\'';
list($type, $data) = explode(';', $data);
list(, $data) = explode(',', $data);
$data = base64_decode($data);
file_put_contents('./photo/' . $filename . '.jpg', $data);

Download Image with Extension from URL using cURL php

I am trying to download GooglePlay app's icons from links provided.
eg. https://lh5.ggpht.com/j0y0xf18PF8iZ_qyKekah11Gg7fteqhqm_VC0SQg7oMsIyMPato7Z_zBsGmOtTf2Fw=w300
now when i am downloading the image, using cURL, using the following code
function scaleImageAndSaveIt($appName,$imageURL){
$format="_%d_%m_%Y_%H_%M_%S";
$strf=strftime($format);
$imageLocnName = $appName . $strf ;
$ch = curl_init($imageURL);
$fp = fopen($imageLocnName, 'wb');
curl_setopt($ch, CURLOPT_FILE, $fp);
curl_setopt($ch, CURLOPT_HEADER, true);
$resp = curl_exec($ch);
echo $resp;
curl_close($ch);
fclose($fp);
return $imageLocnName; }
Now when i am try to save image, i do not have any file extension. (.png, or .jpg or anything else). Though, when i manually save the image, i get the image extension as PNG.
How do i either download the image with default image name and extension or how can I find the extension. Any of the solution would be helpful for me.
try something like this, and based on the return value decide which extension to use:
function GetMimeType($path)
{
//$type = mime_content_type($file); //deprecated
/* //file info -> normal method, but returns wrong values for ics files..
$finfo = finfo_open(FILEINFO_MIME_TYPE); // return mime type ala mimetype extension
$type = $filename.":".finfo_file($finfo, $filename);
finfo_close($finfo);
*/
$forbiddenChars = array('?', '*', ':', '|', ';', '<', '>');
if(strlen(str_replace($forbiddenChars, '', $path)) < strlen($path))
throw new \Exception("Forbidden characters!");
$path = escapeshellarg($path);
ob_start();
$type = system("file --mime-type -b ".$path);
ob_clean();
return $type;
}
function GuessExtension($path)
{
$type = GetMimType($path);
$extension = "";
switch($type)
{
case "image/png":
$extension = ".png";
break;
case "image/jpeg":
default:
$extension = ".jpg";
break;
}
}
//use it like this:
var_dump(GuessExtension("/path/to/your/saved/file"));

cURL Download of image isn't an image

I'm downloading an image via curl from filepicker.io. Here's the downloading code:
if ($_GET['download']== 'true'){
$downloadarray = array();
while($row = mysql_fetch_array($res)){
$url= $row['loc'];
$path = 'tmp/';
$path .= rand(100,999);
$path .= $row['name'];
$fp = fopen($path, 'w');
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_FILE, $fp);
$data = curl_exec($ch);
curl_close($ch);
fclose($fp);
echo print_r($data);
$downloadarray[] = array($path, $row['name']);
}
$zipname = rand(0,9999) . 'download.zip';
$zip = new ZipArchive;
$zip->open($zipname, ZipArchive::CREATE);
foreach ($downloadarray as $file) {
$zip->addFile($file['0'], $file['1']);
}
$zip->close();
header('Content-Type: application/zip');
header('Content-disposition: attachment; filename=' . $zipname);
header('Content-Length: ' . filesize($zipname));
readfile($zipname);
unlink($zipname);
}
For some reason the downloaded file is an image, for example 'palm-tree.jpeg' but it isn't actually being stored as an image. There is no header information being added in the image file. When I open the image with Get Info on my mac a preview correctly renders but the file type is listed as Document. Am I doing something wrong?
EDIT: Now added full code including zipping
Remove:
fwrite($fp, $data);
When you use CURLOPT_FILE, cURL writes the results to the file, you don't need to do it yourself. $data contains true, and you're appending that to the file (actually you're appending 1 to the file, since you're converting true to a string when you write it).

How can I save a file url submitted in a form with curl?

I am trying to create an upload plugin that allows for a user to upload any file from their computer or from a url they type into the provided text field.
This is the script I have to upload files from a local disk:
session_start();
//Loop through each file
for($i=0; $i<count($_FILES['file']); $i++) {
//Get the temp file path
if (isset($_FILES['file']['tmp_name'][$i]))
{
$tmpFilePath = $_FILES['file']['tmp_name'][$i];
}
//Make sure we have a filepath
if ($tmpFilePath != ""){
//Setup our new file path
if (isset($_FILES['file']['name'][$i]))
$newFilePath = "./uploaded_files/" . $_FILES['file']['name'][$i];
}
//Upload the file into the temp dir
if(move_uploaded_file($tmpFilePath, $newFilePath)) {
echo "Uploaded Successfully!<br />";
}
All I need now is for the curl part to take the file from the url submitted in the text field and save it to the same location.
Here is the cURL I have so far:
function GetImageFromUrl($link) {
$ch = curl_init();
curl_setopt($ch, CURLOPT_POST, 0);
curl_setopt($ch,CURLOPT_URL,$link);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$result=curl_exec($ch);
curl_close($ch);
return $result;
}
$sourcecode=GetImageFromUrl("http://domain.com/path/image.jpg");
$savefile = fopen('/home/path/image.jpg', 'w');
fwrite($savefile, $sourcecode);
fclose($savefile);
Is there a specific reason you want to use curl? Here's how you can simply do that without it:
$url = $_POST['url'];
$file_content = file_get_contents($url);
$file_name = array_pop(explode('/', parse_url($url, PHP_URL_PATH)));
file_put_contents('/home/path/' . $file_name, $file_content);
You should also consider looking into $url and checking if it's valid before working with it.

Categories