PHP - zip folder,download, and delete through browser - php

I have found a lot of information about zipping files, but don't know how to download it. I have the following code:
$zip = new ZipArchive;
$zip->open('myzip.zip', ZipArchive::CREATE);
foreach (glob($directory."/*") as $file) {
$zip->addFile($file);
unlink($file);
}
$zip->close();
header('Content-Type: application/zip');
header("Content-Disposition: attachment; filename='myzip.zip'");
header('Content-Length: ' . filesize($zip));
header("Location: myzip.zip");
This code creates the zip file of files that exists in my directory. The file gets created, but it gets created in a random directory that I do not want it to be in. I want to create the zip file of all the files in the directory I specify, have it downloaded in the browser, and then delete the zip file and all the files in my web server. Basically, I want the zip file to be temporary.
Right now the code runs, but nothing is being downloaded and the file is being created in a random directory.

Related

Access & Deliver XML File Above Webroot

I'm trying to load an appcast xml file from a php file, The xml contains a file path used to display a changelog.html & gives a download path to a file. Normally, I don't want browsers to be able to access this stuff, so, the xml file, changelog & the file are all together in folder above the web root directory. The php file is inside of the webroot.
Here's my php code:
$filename = "./home/myaccountusername/folder1/folder2/appcast.xml";
if (!file_exists ($filename)) throw new Exception("File not found");
// Set the content type to xml
header('Content-Type: text/xml');
header('Content-Disposition: attachment; filename="' . basename($filename) . '"');
header('Content-Length: ' . filesize($filename));
// Tell the user-agent (Stacks) not to cache the file
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
// Flush the output buffer
ob_clean();
flush();
// Read the data and send the file
//throw new Exception("FileName: " . $filename);
readfile($filename);
exit;
It's throwing exception: File not found
How do I write the paths to look above the webroot & when passed to my final display interface, allows the changelog.html to be opened & the file to be downloaded?
Note: I've tried the beginning of the path to be /home... and home... & even ../../../folder1/ ...
Is this possible to set up in php? Can't figure it out.
Update1:
Here's a tree of server:
- public_html
- appcastsecure
- productfolder
- appcast.xml
- changelog.html
- productzipfile.zip
- company_folder
- secureappcast
- appcastfile.php (start here for pathing)
I'm using DIR in appcastfile.php which gives path to appcast.xml:
$filename = /home/userdir/public_html/company_folder/secureappcast/../../appcastsecure/productfolder/appcast.xml
My problem is appcast.xml is pushed to clients on their server, so I can't figure out how to set up pathing in appcast.xml so it will point to changelog & productzipfile on my server (all are outside of public_html)
Firstly, the one in your example is trying to access the a folder relative to the current directory...
$filename = "./home/myaccountusername/folder1/folder2/appcast.xml";
The first dot shouldn't be there anyway.
If you want to access a file that is relative to a directory, you can use __DIR__, which gives the directory of the script your currently in. This then depends on where the file your trying to access is relative to the current script. So
$filename = __DIR__."/../appcast.xml";
Is a file in the directory above the one containing this script. You will have to adjust this depending on your particular requirements.

Download in .zip file works with website image but not image from Amazon S3 with signed Url

I have an object with signed Urls to images on Amazon S3. My example is simplified to one image and my goal is to download a zip file with that image.
This image works with my code in the variable $fileUrl
http://google.com/images/logo.png
But not this (in variable $fileUrl), I get a corrupt .zip file. I can open the image in the browser with the signed url.
https://mybucketname.s3.amazonaws.com/94c70e8a-61f6-4f58-a4b7-1679df5a7c1f.jpg?response-content-disposition=attachment%3B%20filename%3D94c70e8a-61f6-4f58-a4b7-1679df5a7c1f.jpg&AWSAccessKeyId=AKIAJNY3GPOFFLQ&Expires=1426371544&Signature=HDNhGKHDsjEgqkMreN3tbozkfzo%3D
$zipName = 'zipfile.zip';
# create new zip opbject
$zip = new ZipArchive();
$fileUrl = 'https://mybucketname.s3.amazonaws.com/94c70e8a-61f6-4f58-a4b7-1679df5a7c1f.jpg?response-content-disposition=attachment%3B%20filename%3D94c70e8a-61f6-4f58-a4b7-1679df5a7c1f.jpg&AWSAccessKeyId=AKIAJNY3GPOFFLQ&Expires=1426371544&Signature=HDNhGKHDsjEgqkMreN3tbozkfzo%3D';
# create a temp file & open it
$tmp_file = tempnam('.','');
$zip->open($tmp_file, ZipArchive::CREATE);
# download file
$download_file = file_get_contents($fileUrl);
#add it to the zip
$zip->addFromString(basename($fileUrl),$download_file);
# close zip
$zip->close();
# send the file to the browser as a download
header('Content-type: application/zip');
header('Content-disposition: attachment; filename='.$zipName);
header('Content-Length: ' . filesize($tmp_file));
readfile($tmp_file);

Add file to a zip file with content while it is downloading php

I want to add a file .txt to a zip file with images.
while the zip is downloading, I want to add the file .txt without affecting the original file.
so, is possible to do this? or the only way is unzip the zip file to a temporary folder, then add the txt file and delete it?
I tried with tmpfile, but it just creates a temporaly file
You can do something like this:
$files = array(
'file1',
'file2'
);
$tmp_file = tmpfile();
$zip->open($tmp_file, ZipArchive::CREATE);
# loop through each file
foreach($files as $file){
# download file
$download_file = file_get_contents($file);
#add it to the zip
$zip->addFromString(basename($file),$download_file);
}
# close zip
$zip->close();
# send the file to the browser as a download
header('Content-disposition: attachment; filename=new-zipfile.zip');
header('Content-type: application/zip');
readfile($tmp_file);

PHP zip from file

Attempting to create a kmz file from a kml file. The script was working last week, but somehow it stopped working. I am attempting to troubleshoot this issue by creating a .zip file which contains a .kml file.
The process is as follows
1. Kml file is created
2. .zip file is added
3. kml file is added to zip according to name
4. .zip is saved
The issue is that when I open the directory the .zip contains that looks like the file structure of the .kml file, not just the file.
For example if the .kml was inside c:/foldera/folderb. The zip would contain c:/foldera/folderb/kml.
$zip = new ZipArchive();
$zip_name = $_SERVER['DOCUMENT_ROOT'] .'/assets/kml'. "/r".$r.".zip";
$filename = $_SERVER['DOCUMENT_ROOT'] .'/assets/kml'. "/r".$r.".kml";
$zip->open($zip_name, ZIPARCHIVE::CREATE);
$zip->addFile($filename);
$zip->close();
unlink($_SERVER['DOCUMENT_ROOT'] .'/assets/kml'. "/r".$r.".kml");
For some reason you have two addfile's:
$zip->addFile($filename, ltrim($filename, '/'));
$zip->addFile($filename);
Try replacing those two lines with this:
$zip->addFile($filename, basename($filename));
basename() returns only the filename, removing the path - http://www.php.net/manual/en/function.basename.php

PHP protected file access

I am using Martin Barker's code/answer from ( PHP to protect PDF and DOC ) almost verbatum, only difference is the file I am protecting is in my user folder above the public_html folder
Folder structure
/users/websupport
/public_html
File to download is at:
/users/websupport/FileToDownload.pdf
The download.php file is at
/public_html/download.php
but Firefox tells me it cannot find the file at Firefox can't find the file at download.php.
I have verified that the file is there via ftp.
If placing the file outside the webroot do I need to add something to the sites .htaccess ? Just not sure where I am going wrong with this. Below is the code within download.php
//check users is loged in and valid for download if not redirect them out
// YOU NEED TO ADD CODE HERE FOR THAT CHECK
// array of support file types for download script and there mimetype
$mimeTypes = array(
'doc' => 'application/msword',
'pdf' => 'application/pdf',
);
// set the file here (best of using a $_GET[])
$file = "../users/websupport/2011cv.pdf";
// gets the extension of the file to be loaded for searching array above
$ext = explode('.', $file);
$ext = end($ext);
// gets the file name to send to the browser to force download of file
$fileName = explode("/", $file);
$fileName = end($fileName);
// opens the file for reading and sends headers to browser
$fp = fopen($file,"r") ;
header("Content-Type: ".$mimeTypes[$ext]);
header('Content-Disposition: attachment; filename="'.$fileName.'"');
// reads file and send the raw code to browser
while (! feof($fp)) {
$buff = fread($fp,4096);
echo $buff;
}
// closes file after whe have finished reading it
fclose($fp);
Make sure the user your php script runs as has read access to that directory.
On php embedded in apache on most debian derivatives, the user will be 'www-data'.
I had the same issue recently where readfile() and fpassthru() just would not work on my server.
What I ended up doing was creating symlinks for the files as needed and passing those to the user. You can learn how to create symlinks here.
I used
exec("ln -s source_file_full_path full_path_to_fake_file");
if you wanted your user to have a link like 'http://somesite.com/folder/fake_file.pdf' then the full path would be to where 'folder' lives on your server and you would include 'fake_file.pdf' in your fake file path.
then to expire the links I made another call to find all of the symlinks with a creation date older than x minutes. You can see how to do that in this answer. (That could be a cron job to ensure they expire on time.)

Categories