Downloading a folder with phpseclib Net_SFTP.get does not work - php

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;

Related

zipArchive how save folder in folder

I'm writing a script that needs to archive folders and files inside, but I can not figure out how to do it if there's another folder inside one folder. I will explain by example, so the norms work
Warning: ZipArchive::close(): Read error: Is a directory in /путь до скрипта/public_html/crm/drive/drive.php on line 102
Folder +
     File1
     File2
     And so on (so it works)
But does not want to work like that
Folder +
       File1
       FOLDER (this does not work)
The question is how to make it so that if the script saw the folder it also downloaded and if I saw the folder inside that folder also downloaded files in the folders, respectively? Here is my script
if (isset($_POST['createPath'])) {//Check that the button is clicked
$zip = new ZipArchive(); // Create an archive
$zip_name = time().".zip"; // file name
if ($zip->open($zip_name, ZipArchive::CREATE) !== true) { // open file
die ("Could not open archive");//If the file does not open
}
$var = $_POST["pathUpload"];// Array of variables that are passed through the form
foreach ($var as $key_var) {// We process the array in a loop
$iterator = new RecursiveDirectoryIterator($key_var);//There is a recursive search of the file system directories
foreach ($iterator as $key => $value) {// We process an array of files
$path = pathinfo($value);//Check the path or revert the path to the file
if ($path['basename'] == '.' || $path['basename'] == '..') continue;//Check those files that you download if there are points in the files then download
$zip->addFile(realpath($key), $key);//Add the file to the server
}
$zip->close();//Close archive
if (file_exists($zip_name)) {
// Give the file to download
header('Content-type: application/zip', 'charset=utf-8');
header('Content-Disposition: attachment; filename="'.$zip_name.'"');
ob_end_flush();//Buffering since without it nothing will work
readfile($zip_name); //Read the file
unlink($zip_name);//Delete the variable
}
}
}
The error because you are trying to add directory to Zip with method
// this function only for adding files!
public function addFile ($filename, $localname = null, $start = 0, $length = 0) {}
the method allows you to add directory
public function addEmptyDir ($dirname) {}
The other issue you have, is you are using directory iterator in wrong way.
// this way only loop on directories in
$iterator = new RecursiveDirectoryIterator($key_var);//There is a recursive search of the file system directories
the right way is to use RecursiveIteratorIterator on RecursiveDirectoryIterator - have a look the options in the docs.
example:
// the right way to recursive get list of the file system directories and files
$iterator = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator($key_var, RecursiveDirectoryIterator::SKIP_DOTS), // skip . and ..
RecursiveIteratorIterator::SELF_FIRST,
RecursiveIteratorIterator::CATCH_GET_CHILD // Ignore "Permission denied"
);
so to get it to work, your code should look like this:
<?php
if (isset($_POST['createPath'])) {//Check that the button is clicked
$zip = new ZipArchive(); // Create an archive
$zip_name = time() . ".zip"; // file name
if ($zip->open($zip_name, ZipArchive::CREATE) !== true) { // open file
die ("Could not open archive");//If the file does not open
}
$var = $_POST["pathUpload"];// Array of variables that are passed through the form
foreach ($var as $key_var) {// We process the array in a loop
// There is a recursive search of the file system directories
$iterator = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator($key_var, RecursiveDirectoryIterator::SKIP_DOTS), // skip . and ..
RecursiveIteratorIterator::SELF_FIRST,
RecursiveIteratorIterator::CATCH_GET_CHILD // Ignore "Permission denied"
);
// all directories and subdir
foreach ($iterator as $path => $dir) {
if (!$dir->isDir()) && is_file($path) {
$zip->addFile(realpath($path)); //Add the file to the server
}
if ($dir->isDir()) {
// do nothing
}
}
$zip->close(); //Close archive
if (file_exists($zip_name)) {
// Give the file to download
header('Content-type: application/zip', 'charset=utf-8');
header('Content-Disposition: attachment; filename="' . $zip_name . '"');
ob_end_flush();//Buffering since without it nothing will work
readfile($zip_name); //Read the file
unlink($zip_name);//Delete the variable
}
}
}
happy coding :)

PHP ZipArchive is not adding any files (Windows)

I'm failing to put even a single file into a new zip archive.
makeZipTest.php:
<?php
$destination = __DIR__.'/makeZipTest.zip';
$fileToZip = __DIR__.'/hello.txt';
$zip = new ZipArchive();
if (true !== $zip->open($destination, ZIPARCHIVE::OVERWRITE)) {
die("Problem opening zip $destination");
}
if (!$zip->addFile($fileToZip)) {
die("Could not add file $fileToZip");
}
echo "numfiles: " . $zip->numFiles . "\n";
echo "status: " . $zip->status . "\n";
$zip->close();
The zip gets created, but is empty. Yet no errors are triggered.
What is going wrong?
It seems on some configuration, PHP fails to get the localname properly when adding files to a zip archive and this information must be supplied manually. It is therefore possible that using the second parameter of addFile() might solve this issue.
ZipArchive::addFile
Parameters
filename
The path to the file to add.
localname
If supplied, this is the local name inside the ZIP archive that will override the filename.
PHP documentation: ZipArchive::addFile
$zip->addFile(
$fileToZip,
basename($fileToZip)
);
You may have to adapt the code to get the right tree structure since basename() will remove everything from the path apart from the filename.
You need to give server right permission in folder where they create zip archive. You can create tmp folder with write permision chmod 777 -R tmp/
Also need to change destination where script try to find hello.txt file $zip->addFile($fileToZip, basename($fileToZip))
<?php
$destination = __DIR__.'/tmp/makeZipTest.zip';
$fileToZip = __DIR__.'/hello.txt';
$zip = new ZipArchive();
if (true !== $zip->open($destination, ZipArchive::OVERWRITE)) {
die("Problem opening zip $destination");
}
if (!$zip->addFile($fileToZip, basename($fileToZip))) {
die("Could not add file $fileToZip");
}
echo "numfiles: " . $zip->numFiles . "\n";
echo "status: " . $zip->status . "\n";
$zip->close()
check this class to add files and sub-directories in a folder to zip file,and also check the folder permissions before running the code,
i.e chmod 777 -R zipdir/
HZip::zipDir('/path/to/sourceDir', '/path/to/out.zip');
<?php
class HZip
{
private static function folderToZip($folder, &$zipFile, $exclusiveLength) {
$handle = opendir($folder);
while (false !== $f = readdir($handle)) {
if ($f != '.' && $f != '..') {
$filePath = "$folder/$f";
// Remove prefix from file path before add to zip.
$localPath = substr($filePath, $exclusiveLength);
if (is_file($filePath)) {
$zipFile->addFile($filePath, $localPath);
} elseif (is_dir($filePath)) {
// Add sub-directory.
$zipFile->addEmptyDir($localPath);
self::folderToZip($filePath, $zipFile, $exclusiveLength);
}
}
}
closedir($handle);
}
public static function zipDir($sourcePath, $outZipPath)
{
$pathInfo = pathInfo($sourcePath);
$parentPath = $pathInfo['dirname'];
$dirName = $pathInfo['basename'];
$z = new ZipArchive();
$z->open($outZipPath, ZIPARCHIVE::CREATE);
$z->addEmptyDir($dirName);
self::folderToZip($sourcePath, $z, strlen("$parentPath/"));
$z->close();
}
}

Zip file add and rename with php

I have this piece of code..,everything works fine ,but an issue with renaming
$zip = new ZipArchive();
$zipPath = 'images/userfiles/'.$company_details->company_name.'_products.zip';
$emptydir = $company_details->company_name.'_product_logos';
if ($zip->open($zipPath, ZIPARCHIVE::CREATE | ZIPARCHIVE::OVERWRITE)) {
$new_filename = substr($my_file, strrpos($my_file, '/') + 1);
$zip->addFile($my_file, $new_filename);
$zip->addEmptyDir($emptydir);
foreach($parts_list as $pl) {
if(!empty($pl['part_image'])){
if (file_exists($_SERVER['DOCUMENT_ROOT'] . $baseurl . '/images/group-logo/' . $pl['part_image'])) {
$img_file = 'images/group-logo/' . $pl['part_image'];
$new_filename2 = substr($img_file, strrpos($img_file, '/') + 1);
$zip->addFile($img_file,$emptydir . '/' . $new_filename2);
/*********the problem here******
Is there any way to rename the file that i added on the previous line to something else ,already tried zip rename and renameindex but not working
for example i want to rename the file $new_filename2 to $new_filename2.'something' with out affecting the original file's name
P.S the files to be renamed are inside another folder in the zip
*******************************/
}
}
}
$zip->close();
}
Since you do not want to effect the original file I would think that you are going to need to include a copy statement. Something like;
$file = '$new_filename2';
$newfile = '$new_filename2.zip';
if (!copy($file, $newfile)) {
echo "failed to copy $file...\n";
Okay i figured it out
Zip creates a lock on the file..you cant rename on the fly ,close it and rename again
$zip->addFile('.....');
....
$zip->close();
and open zip again and rename

PHP ZipArchive download working but not adding files to zip

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.

PHP zip does not work

I made a drupal module, one of function of the module is to compress some files to be a zip package. It works fine in my local environment(xampp), but fails on server. My server does has php zip extension enabled, since I can see zip information on php info and I can unzip file with php as well.
Besides, I already chmod files to be 0777 .
My code:
$folder = file_directory_path();
$zip = new ZipArchive();
if ($zip->open('b.zip', ZIPARCHIVE::CREATE) === TRUE) {
foreach ( $files as $file ) {
drupal_set_message(t($file)); // I can see the the message on this stpe
$zip->addFile($file);
}
$zip->close();
if (file_exists('b.zip')) {
copy('b.zip', $folder . '/b.zip');
unlink('b.zip');
global $base_url;
variable_set('zippath', $base_url . $folder . '/b.zip');
drupal_set_message(t('new zip package has been created'));
}
} else {
drupal_set_message(t('new zip package failed'));
}
Yes .. i know what you mean .. this are the 3 possibility
You have write permissions
You Did not use full path
You are including folders as file
You can try this
error_reporting(E_ALL);
ini_set("display_errors", "On");
$fullPath = __DIR__ ; // <-------- Full Path to directory
$fileZip = __DIR__ . "/b.zip"; // <--- Full path to zip
if(!is_writable($fullPath))
{
trigger_error("You can't Write here");
}
$files = scandir($fullPath); // <--- Just to emulate your files
touch($fileZip); // <----------------- Try Creating the file temopary
$zip = new ZipArchive();
if ($zip->open($fileZip, ZIPARCHIVE::CREATE) === TRUE) {
foreach ( $files as $file ) {
if ($file == "." || $file == "..")
continue;
$fileFull = $fullPath . "/$file";
if (is_file($fileFull)) { // <-------------- Make Sure its a file
$zip->addFile($fileFull, $file);
}
// Play your ball
}
$zip->close();
} else {
echo "Failed";
}
I would recommend you to use rar or zip command to make zip. I am using linux and doing in my php system as
$folder = 'your_folder'; // folder contains files to be archived
$zipFileName = 'Your_file_name'; // zip file name
$command = 'rar a -r ' . $zipFileName . ' ' . $folder . '/';
exec($command);
Its very quick. but you need to install rar package in your system.
Thanks

Categories