php recursive iterator fails on file rename - php

I am having issue with RecursiveIteratorIterator moving to next item. I have a directory which has multiple files, and I am trying to go to each file, rename it, and do some other stuff on it. The RecursiveIteratorIterator picks the first file from the directory and renames it successfully. When I do $it->next(), it stays on same file, and tries to look for the file which was already renamed to something else. Below is my code sample. File permission are set to 777. Any ideas would be appreciated.
This only happens if I rename the file. If I remove renaming functionality, its moves to next item as expected.
//initialize iterator object
$it = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($directory, 0));
/* loop directly over the object */
while ($it->valid()) {
// check if value is a directory
if (!$it->isDot()) {
if (!is_writable($directory . '/' . $it->getSubPathName())) {
//direcotry not writable, throw error
} else {
// get current file info
$fileinfo = pathinfo($it->getSubPathName());
//get file extension
$ext = $fileinfo['extension'];
//if its a '.', move to next item
if (in_array($fileinfo['filename'], array(".", ".."))) {
$it->next();
}
// the current file name with complete path
$old_file = $directory . '/' . $it->getSubPathName();
throw new Exception('source file doesnot exist ' . $old_file, error::DOESNOTEXIST);
}
//generate new file name with path
$new_file = $directory . '/' . $it->getSubPath() . '/' . $filename . '.' . $ext;
//rename the file
rename($old_file, $new_file);
}
}
/* * * move to the next iteration ** */
$it->next();
}

Related

I need to create .Zip file in Laravel and my code does not work

this is the 1st time I posted on StackOverflow. I need to create a zip file of multiple images. I've tried Zipper and also ZipArchive and my code still fails.
$zip = new \ZipArchive();
foreach ($students as $student) {
$download = 'album' . $student->album_id . '.zip';
if ($zip->open(public_path('albums/' . $student->album_id . '/' . $download), \ZipArchive::CREATE) === TRUE) {
$files = Storage::allFiles('public/albums/' . $student->album_id . '/image_files');
foreach ($files as $file) {
$zip->addFile($file);
}
$zip->close();
}
}
I can assure that all the images exist. I put the images in Storage/app/public/albums/$student->album_id/image_files/. Please help me.
First, you can add an additional step to verify that your file exists by using PHP built in function: file_exists()
Most times, if you your files do noT exists, no files will be added to the zip, and your code will run without throwing any error but still will not work.
What you're passing to addFile() is not a correct path. addFile() needs an absolute path to where your file is stored. You will need to add this line $file_path = storage_path("app/{$file}");
See code below:
$zip = new \ZipArchive();
foreach ($students as $student) {
$download = 'album' . $student->album_id . '.zip';
if ($zip->open(public_path('albums/' . $student->album_id . '/' . $download), \ZipArchive::CREATE) === TRUE) {
$files = Storage::allFiles('public/albums/' . $student->album_id . '/image_files');
foreach ($files as $file) {
$file_path = storage_path("app/{$file}");
if (file_exists($file_path)) {
$zip->addFile($filepath);
}
}
$zip->close();
}
}
Optionally, if you wish to download any of the zipped files, you can return the download response at the end of your code to download:
return response()->download(public_path('albums/' . $student->album_id . '/' . $download));

Putting created file to date folder

I made some file name.
First I need to create folder with year and month and then in that folder to put my new created csv file.
Everything seems to be working except the part where I need to put that csv file in new created folder.
File is created and folder is created.
Can someone help with the trick.
It puts it outside the folder.
My code:
// get directory path to save csv files
$rootDir = $this->container->get('kernel')->getRootDir();
$dir = $rootDir . '/../web/uploads/files/';
// makeing new directory by date
if(!is_dir($dir . date('Y-m'))) {
mkdir($dir . date('Y-m'), 0777, true);
}
// generating csv file name
$fileName = 'export-'.date('Y-m-d').'.csv';
$fp = fopen($dir .$fileName, 'w');
You create a folder with the year and month, but you never add the new folder to your $dir-variable.
Try this:
$rootDir = $this->container->get('kernel')->getRootDir();
// Let's add the full destination here (including the month-dir)
$dir = $rootDir . '/../web/uploads/files/' . date('Y-m');
// Now we don't need to append the date since it's already included
if(!is_dir($dir)) {
mkdir($dir, 0777, true);
}
// generating csv file name
$fileName = 'export-'.date('Y-m-d').'.csv';
// Just add a / and the filename and it should be the correct path
$fp = fopen($dir . '/' . $fileName, 'w');

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();
}
}

Execute second statement if the first one holds

If a directory does not exist, i create the directory and save a file, i can also just save a file if the directory exists. One file should be created at a time not all at the same time as the code below does. If the first file is created now then the next should only be created when the function is called. The files are Named R1,R2....Rn. How can I achieve this, This creates them all at the same time
$fileName1=$fileName1='somedir/'.$thedir.'/'.$thefile.'_R1.xlsx';
...
if (!dir($dirName))
{
mkdir('somedir/' . thedir, 0777);
$objWriter->save($fileName);
}
if (dir($dirName) && (!file_exists($fileName)))
{
$objWriter->save($fileName);
}
if (dir($dirName) && file_exists($fileName))
{
$objWriter->save('somedir/' . $thedir . '/' . $thefile . '_R1.xlsx');
}
if (dir($dirName) && file_exists($fileName1))
{
$objWriter->save('somedir/' . $thedir . '/' . $thefile . '_R2.xlsx');
}
...
if (!is_dir($dir))
mkdir($dir, 0777);
$suffixes = array('_R1.xlsx', '_R2.xlsx');
foreach($suffixes as $suffix) {
$fileName = $dir.'/' . $thefile . $suffix;
if (! file_exists($fileName)) {
$objWriter->save($fileName);
break;
}
}
You have to add error handling, and note that just checking for a file can create concurrency issues (two processes trying both seeing that the file doesn't exist and try to create it).
You will need to use the [is_dir][1] function to check if a folder exists.
Check out this code - a bit of a rework from yours
$fileName1=$fileName1='somedir/'.$thedir.'/'.$thefile.'_R1.xlsx';
....
// Directory does not exist - create it
if (!is_dir($dirName))
{
mkdir('somedir/' . thedir, 0777);
$objWriter->save($fileName);
}
// Directory exists
if (is_dir($dirName))
{
// File does not exist - create it
if (!file_exists($fileName)))
{
$objWriter->save($fileName);
}
// Check one more time if the file exists
if (file_exists($fileName)))
{
$objWriter->save('somedir/' . $thedir . '/' . $thefile . '_R1.xlsx');
$objWriter->save('somedir/' . $thedir . '/' . $thefile . '_R2.xlsx');
}
}
.......

Move file into a specific folder

I have a question regarding file handle, i have:
Files:
"Mark, 123456, HTCOM.pdf"
"John, 409721, JESOA.pdf
Folders:
"Mark, 123456"
"Mark, 345212"
"Mark, 645352"
"John, 409721"
"John, 235212"
"John, 124554"
I need a routine to move files to correct folders.
In case above, i need to compare 1st and second value from file and folder. If are the same i move the file.
Complement to post:
I have this code, work right but i need to modify to check name and code to move files...
I'm confused to implement function...
$pathToFiles = 'files folder';
$pathToDirs = 'subfolders';
foreach (glob($pathToFiles . DIRECTORY_SEPARATOR . '*.pdf') as $oldname)
{
if (is_dir($dir = $pathToDirs . DIRECTORY_SEPARATOR . pathinfo($oldname, PATHINFO_FILENAME)))
{
$newname = $dir . DIRECTORY_SEPARATOR . pathinfo($oldname, PATHINFO_BASENAME);
rename($oldname, $newname);
}
}
As a rough-draft and something that will only work with your specific case (or any other case following the same naming pattern), this should work:
<?php
// define a more convenient variable for the separator
define('DS', DIRECTORY_SEPARATOR);
$pathToFiles = 'files folder';
$pathToDirs = 'subfolders';
// get a list of all .pdf files we're looking for
$files = glob($pathToFiles . DS . '*.pdf');
foreach ($files as $origPath) {
// get the name of the file from the current path and remove any trailing slashes
$file = trim(substr($origPath, strrpos($origPath, DS)), DS);
// get the folder-name from the filename, following the pattern "(Name, Number), word.pdf"
$folder = substr($file, 0, strrpos($file, ','));
// if a folder exists matching this file, move this file to that folder!
if (is_dir($pathToDirs . DS . $folder)) {
$newPath = $pathToDirs . DS . $folder . DS . $file;
rename($origPath, $newPath);
}
}

Categories