PHP ZipArchive download working but not adding files to zip - php

I know there is many questions regarding the ZipArchive and how it works but after following all these I still can't get my program to work.
I don't know where i'm going wrong because I have die methods in and none of them are getting activated.
$path = "/export/scripts/CLOUD/logs/web/Private_Testbox/Jan_28_2013_16_20_44_atvts78_rollout_config/";
$fileName = explode('/', $path);
$zipname = $fileName[count($fileName) - 2];
$zip = new ZipArchive;
$handle = opendir($path);
//Check whether Zip can be opened
if ($zip->open($zipname, ZIPARCHIVE::CREATE) !== TRUE) {
die("Could not open archive");
}
//Add all files to an array
while ($file = readdir($handle))
{
$zip->addFile($path, $file);
}
closedir($handle);
$zip->close();
//Send zip folder
header('Content-Type: application/zip');
header('Content-disposition: attachment; filename=' . $zipname . '.zip');
readfile($zip);
This file downloads the zip folder but there is never anything in it.
Thanks for help in advance.

You forgot a die() on the ->addFile() call, which means you're assuming that the files actually got added.
readfile() does not return the full path to a file in a directory, only the actual "local" filename, which means you're adding files which don't exist in the script's current working directory. Try:
$zip->addFile($file, $path . $file);
^^^^^^^^^^^^^^^^^^^^^
instead. As it stands now, your code is using $path as the filename to embed in the zip, and directories cannot be used as filenames. And without the $path . $file, addFile is looking in the wrong spot, e.g. it's the equivalent of getcwd() . $file instead.

Related

Downloading a folder with phpseclib Net_SFTP.get does not work

I am trying to access a file in an SFTP folder server using phpseclib. But when I try using $sftp->get, it returns false. I am not sure how to debug the problem at all.
public function get_file_from_ftps_server()
{
$sftp = new \phpseclib\Net\SFTP(getenv('INSTRUM_SERVER'));
if (!$sftp->login(getenv('INSTRUM_USERNAME'), getenv('INSTRUM_PASSWORD'))) {
exit('Login Failed');
}
$this->load->helper('file');
$root = dirname(dirname(__FILE__));
$root .= '/third_party/collections_get/';
$path_to_server = 'testdownload/';
$result = $sftp->get($path_to_server, $root);
var_dump($result);
}
In the $result, I get a false and I am not sure why its happening, I read their documentation but still not sure. Root is the directory where I want my information to be stored. Right now I only added a trial.xml file there, but also wondering how can I get multiple files if its in the folder.
Here is a picture of the server structure:
Normally when I use sftp, I normally change directory and then try to download the information.
$sftp->pwd(); // This will show you are in the root after connection.
$sftp->chdir('./testdownload'); // this will go inside the test directory.
$get_path = $sftp->pwd()
//If you want to download multiple data, use
$x = $sftp->nlist();
//Loop through `x` and then download the file using.
$result = $sftp->get($get_path); // Normally I use the string information that is returned and then download using
file_put_contents($root, $result);
// Root is your directory, and result is the string.
The Net_SFTP.get method can download a single file only. You cannot use it to download a whole directory.
If you want to download whole directory, you have to use one of the "list" methods (Net_SFTP.nlist or Net_SFTP.rawlist) to retrieve list of files and then download the files one-by-one.
<?php
use phpseclib\Net\SFTP;
$sftp = new SFTP("server");
if(!$sftp->login("username", "password")) {
throw new Exception("Connection failed");
}
// The directory you want to download the contents of
$sftp->chdir("/remote/system/path/");
// Loop through each file and download
foreach($sftp->nlist() as $file) {
if($file != "." && $file != "..")
$sftp->get("/remote/system/path/$file", "/local/system/path/$file");
}
?>
I'm a bit late but nonetheless I wanted to share this.
The approach I take is to use zip files to download folders. The reason for this is that you will have a feedback that something is being downloaded.
If you don't want that, simply remove the things related to zip. Then, remove the headers and replace them with $sftp->get("remote/file", "local/file");
<?PHP
use phpseclib\Net\SFTP;
$sftp = new SFTP("IP:Port");
if(!$sftp->login("username", "password")) throw new Exception("Connection failed");
# Create directory variable
$directory = "/remote/path/";
# Set directory
$sftp->chdir($directory);
# File Name
$name = 'file';
# Retrieve file
$file = $sftp->get('file');
# Check if is folder
if ($sftp->is_dir($file)) {
# Temporarily file
$tmp = sys_get_temp_dir()."\\yourSite_".rand().".zip";
# Create new Zip Archive.
$zip = new ZipArchive();
# Open new Zip file
$zip->open($tmp, ZipArchive::CREATE | ZipArchive::OVERWRITE);
function recursive($src, $zip, $sftp) {
# Loop Through files
foreach ($sftp->nlist($src) as $file) {
# Skip . & ..
if ($file == "." || $file == "..") continue;
if (!$sftp->is_file($src . "/" . $file)) {
# Make directory
$zip->addEmptyDir($src . "/" . $file);
# Run the loop again
recursive($src . "/" . $file, $zip, $sftp);
} else {
# Add file to zip within folder
$zip->addFromString($src . "/" . $file, $sftp->get($src . "/" . $file));
}
}
}
# Run Recursive loop
recursive($name, $zip, $sftp);
# Close zip file
$zip->close();
header('Content-Description', 'File Transfer');
header('Content-type', 'application/zip');
header('Content-Disposition', 'attachment; filename="' . $name . '.zip"');
header('Content-length', filesize($tmp));
echo file_get_contents($tmp);
# Delete temporarily file
unlink($tmp);
return;
}
# Otherwise download single file
header("Content-Description: File Transfer");
header("Content-Disposition: attachment; filename=\"". $name ."\"");
echo $file;
return;

not able to create zip file in codeigniter

Below is the code to generate the zip of multiple files:
<?php
$file1 = 'D:/xampp/htdocs/pdf/pdffiles/14816393105-annexc-form.pdf';
$file2 = 'D:/xampp/htdocs/pdf/pdffiles/14816393105-resident-form.pdf'
$files = array($file1,$file2);
$zipname = time().'-file.zip';
$zip = new ZipArchive;
$zip->open($zipname, ZipArchive::CREATE);
foreach ($files as $file) {
$zip->addFile($file);
}
$zip->close();
header('Content-Type: application/zip');
header('Content-disposition: attachment; filename='.$zipname);
header('Content-Length: ' . filesize($zipname));
readfile($zipname);
?>
This code does create the zip file but it is corrupted.
EDIT:
zip file is created but if i extract it then it is from the D:/ drive. Means zip file contains this:xampp\htdocs\pd‌​f\pdffiles\file1.pdf
You may specify a filename in addFile method. It is not obvious, since there are no noticeable examples around, but you can use $localname (second parameter) to define and control file/directory structure inside the zip. Use it if you do not want files to be included with their absolute directory tree.
Here is a working example using basename:
$file1 = 'D:/xampp/htdocs/pdf/pdffiles/14816393105-annexc-form.pdf';
// ...
$zip->addFile($file1, basename($file1));
basename returns trailing name component of path, so it will just keep 14816393105-annexc-form.pdf and add it to your zip.

Downloading multiple files using PHP ZipArchive

I am trying to randomly download some files.
I apologize because I posted it earlier but can someone explain what I am doing wrong in detail?
I can not seem to debug it as I know minimal php.
<?php
$rootPath = realpath('./uploads');
//make zip file
$zip = new ZipArchive();
$zip->open('file.zip', ZipArchive::CREATE | ZipArchive::OVERWRITE);
$nfiles = glob($rootPath.'*.{aiff}', GLOB_BRACE);
$files = array_rand($nfiles, 20);
foreach($files as $file) {
$pathtofile = $nfiles[$file];
if (!$file->isDir())
{
// Get path for current file
$filePath = $pathtofile->getRealPath();
$relativePath = str_replace($rootPath, "", $file);
// Add file to zip
$zip->addFile($filePath, $relativePath);
}
}
//-------------------------------------------//
$zip->close();
header('Content-Type: application/zip');
header('Content-disposition: attachment;
filename='.'generatedsounds.zip');
header('Content-Length: ' . filesize('file.zip'));
readfile('file.zip');
if(file_exists('file.zip'))
{
unlink('file.zip');
}
?>
You're calling ->isDir() method which is not defined, And you're calling ->getRealPath() which is also not defined.
And you're getting all files then selecting 20 random files from the array (why??)
While you are rewriting the headers, errors won't be shown in browser, try without rewriting headers which means it's kept as html header and test until you get a binary file output then add the headers back so you have a working code.

ZIP file download php readfile() error

I know this question is posted in this forum for many times, but trust me I have tried all the possible solutions suggested but it didn't work for me.
I am trying to download multiple files using zip, though the zip file gets downloaded successfully, its corrupt and I encounter error after opening it in notepad:
Warning: readfile(E:\Downloads/IMG-20140831-WA0000.zip) [function.readfile]: failed to open stream: No such file or directory in...
I tried all the possible solutions mentioned in the forum such as header-check, web server user has write permission to the folder where I am creating the ZIP file, error-checking before downloading etc. but it did't worked out.
After performing error checking, I encountered something like
Error creating ZIP file : IMG-20140831-WA0000.zip
My code snippet:
function zipFilesDownload($file_names, $archive_file_name, $file_path) {
$zip = new ZipArchive;
if ($zip->open($archive_file_name, ZipArchive::CREATE) !== TRUE) {
exit("cannot open <$archive_file_name>\n");
}
foreach($file_names as $files) {
$zip->addFile($file_path . $files, $files);
}
if ($zip->close() === false) {
exit("Error creating ZIP file : " . $archive_file_name);
}
if (file_exists($archive_file_name)) {
header("Content-Description: File Transfer");
header("Content-type: application/zip");
header("Content-Disposition: attachment; filename=" . $archive_file_name . "");
header("Pragma: no-cache");
header("Expires: 0");
readfile("E:\Downloads/" . $archive_file_name);
ob_clean();
flush();
exit;
} else {
exit("Could not find Zip file to download");
}
}
$fileNames = array(
'D:\\xampp\htdocs\BE\Multimedia/' . $fullName,
'D:\\xampp\htdocs\BE\Decrypt/' . $decrypt_file
);
$zip_file_name = $actualName . '.zip';
$file_path = dirname("E:\Downloads") . '/';
zipFilesDownload($fileNames, $zip_file_name, $file_path);
Please suggest some solutions.
The problem looks to be this line:
$file_path = dirname("E:\Downloads") . '/';
The dirname function "Returns parent directory's path". This means that $file_path will be E:\.
In your function you are using $file_path in the $zip->addFile() method, to refer to the file that should be added to the ZIP archive.
In other words, if you have an array of files, like:
$files = array(
'file1.txt',
'file2.txt',
'file3.txt',
);
Then the files that will be added to the archive will be:
E:\file1.txt
E:\file2.txt
E:\file3.txt
What you probably want is to have these files added:
E:\Downloads\file1.txt
E:\Downloads\file2.txt
E:\Downloads\file3.txt
As far as I can see, to fix your code you simply need to not use dirname(), like this:
$file_path = "E:\Downloads\\";

How to make the contents in a directory to be downloaded as a ZIP file using PHP?

I have lots of files in a particular Directory. In a certain PHP page I lists the contents of the particular directory with links to download each item separately. Now I need to display a Link which will ZIP all the contents of that directory so any visitor can download all the contents as a Single ZIP file.
Use ZipArchive for zipping files and RecursiveDirectoryIterator for getting all files in a directory
something like
$zipfilename = <zip filename>;
$zip = new ZipArchive();
$zip->open($zipfilename, ZipArchive::CREATE);
// add all files in directory to zip
foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator('path/to/files/')) as $filename) {
$zip->addFile($filename);
}
$zip->close();
Then send the zip to the browser
header('Content-Type: application/zip');
header('Content-disposition: attachment; filename="'. $zipfilename .'"');
header('Content-Length: ' . filesize($zipfilename));
readfile($zipfilename);
Obviously you could post the directory name and event the zip file name to the script but it gives you a starting point
Try this
$files = array('file1.txt', 'file2.txt', 'file3.txt');
$zip = new ZipArchive;
$zip->open('file.zip', ZipArchive::CREATE);
foreach ($files as $file) {
$zip->addFile($file);
}
$zip->close();

Categories