PHP: moving directories with contents? - php

I'm having an array $bundle that stores filenames and directory names.
I'm running through the array with a foreach loop and I want to move them inside of another directory. I'm using the rename method therefore and it works pretty fine with JUST FILES.
However directories with other files in there don't respond to the rename() method.
$folder = 'files';
foreach ($bundle as $value) {
$ext = pathinfo($value, PATHINFO_EXTENSION);
if ($ext != "") { //if $value has no suffix it's a fil
rename(PATH . '/' .$value, $folder . '/' . $value);
}
if ($ext == "") { // it's a folder/directory
//rename doesn't work for directories with contents
//what method should i use here???
}
}
I know the pathinfo() method is not the best way to find out if it's a directory or not, however for my little project it's fine. I just need to know how I can move any directory with all it's contents into the "files" folder.
Thank you for your help.

You will have to get all the filenames in that directory using glob or scandir. Then you would have to loop through them with the rename and move them.
Your other option, if you host allows it, is to use shell_exec and do the mv for linux or copy / xcopy for windows command and move them that way. If you choose the exec route, make sure to secure the input etc to prevent any bad stuff from happening.

Related

How to store multiple uploaded files with Laravel's Storage Facade

Currently I have a project that is running Laravel 5.8 and I am trying to use a form that allows user's to upload their own images to the site and store it in the public folder. When trying to use the Storage facade with the 'put' method, a path gets returned but the images do not actually get stored.
if ($request->hasfile('images')) {
foreach ($request->file('images') as $file) {
$path = Storage::disk('public')->put('images', $file);
echo $path;
}
}
This is the code I am trying to use. The path gets echo'd as it should and I have not made any changes to the filesystem config. In the form, the input field images allows for submitting multiple files and the form does hasenctype="multipart/form-data". The $file variable also contains an instance of Illuminate\Http\UploadedFile.
The previous code I used which did work was:
if ($request->hasfile('images')) {
foreach ($request->file('images') as $file) {
$file->move(public_path('images'), $file->getClientOriginalName());
}
}
I would be okay with using my previous code if Laravel can give it a unique file name on upload but what would be causing my code with the Storage facade to not save the images properly? Does the put function just not work like that or is there something I am overlooking?
Edit:
So I realise the images were in fact saving correctly as they should be. I was looking inside the public folder rather than the storage folder which is why my second code example 'worked' but not the first. I realise when using the Storage facade I need to make use of Symbolic linking if I want to access these files on the web.
You need to also make sure you have created the symbolic link on your Ubuntu server or Windows development machine to the storage folder.
Windows you can use : mklink /j /path/to/laravel/public/youfolder /path/to/laravel/storage/youfolder
Ubuntu: ln -s /path/to/laravel/public/youfolder /path/to/laravel/storage/youfolder
To check & set you can also use use php artisan storage:link
Hope this helps
if ($request->hasfile('images')) {
foreach ($request->file('images') as $file) {
$path = Storage::disk('public')->put('images', $file);
$new_file_name = time() . "_" . uniqid() . "_" . $file->getClientOriginalName();
$path = Storage::disk('public')->put($new_file_name, file_get_contents($file));
echo $path;
}
}

FTP Delete All Folders in Target Directory

What i am trying to do is to delete all files in my target servers folder, the folder all the files are in is: "/public_html/" this directory contains all the target files, i don't want to delete this folder as it must remain the intact, just everything inside.
function ftpDelete($conn, $directory) {
echo "<pre><b>FTP Files on Server:</b>\n";
$filelist = ftp_nlist($conn, $directory);
foreach($filelist as $file) {
// Do not show "." or ".."
if ($file != "." && $file != "..") {
ftp_delete($conn, $directory);
echo $file . "\n";
}
}
echo "</pre>";
}
// Run delete functions ...
ftpDelete($conn, "/public_html/");
// Files out that is still on the server ...
FTP Folders on Server:
/public_html/vendor
/public_html/stats
/public_html/icon
/public_html/images
This code so far will delete all files that is the "public_html" directory, but not any folders, i know from reading the folders need to be empty first, i'm not sure the best way to handle these folders, i didn't see a command that would delete the target folders and it's contents, any help would be appreciated.
You need to append the filename after the directory:
ftp_delete($conn, "$directory/$file");

Path to a file in a different drive?

My php file is here:
D:/Appserv/www/x/y/file.php
I want to load stuff from this folder:
E:/foldie
I don't know what path will lead me there.
$somePath="HELP ME HERE!!!!"
$dir=opendir($somePath);
//looping through filenames
while (false !== ($file = readdir($dir))) {
echo "$file\n";
}
Use full Windows path to the file it should be working: "E:\folder\file.txt"
or just copy the file in the local/project directory for testing purpose.
Set $somePath = "e:\\foldie". If that doesn't work, please indicate to us how it fails.
[Edit:: make sure you escape your backslashes in strings]

directory listing with restrictions

I am trying to make a script that lists only folders within a folder. The thing is that I have users who can create folders within their folders so basically what I'm trying to do is to have a way for users to manage their folders and storing files... My problem is that I want to make php "think" that the root folder is their home directory and they cannot go upper than their home directory. Currently my php function doesn't do that, it only shows the content of the directory...and if the user goes one level up and again one level up ...and so on....he could browse the entire hard drive.
function directoryList($path) {
$dirStruct = array();
if(is_dir($path)) {
$handle = opendir($path);
while(($file = readdir($handle)) !== false) {
if(#opendir($path.$file)) {
chdir($path.$file);
$absolutepath = getcwd();
$dirStruct[] = array('path' => $absolutepath.'\\', 'name'=>$file);
}
}
}
return $dirStruct;
}
Instead of giving the user an absolute path, only allow them to specify paths which are relative to a given base path. Next, write a function which removes any "/../" for the relative path and you're safe (as long as users can't create links on the server ...).
If you want to be nice, you can match the ".." with the element before that (so "a/../b" would become "b", i.e. the ".." remove the "a") or ignore the ".." if there is no path element before it.
Here is a little something to expand on:
function listFolders($folderPath, $homeFolder)
{
$folderPath = realpath($folderPath);
$homeFolder = realpath($homeFolder);
if(strpos($folderPath, $homeFolder) === 0) {
return glob("$folderPath/*", GLOB_ONLYDIR);
}
}
$dirs = listFolders('/home/gordon/code/php', '/home/gordon');
print_r($dirs);
For $folderPath you pass in the folder you want to list the directories from. For $homeFolder pass in the folder you want to be the top most folder. By realpathing both paths you make sure they are resolved to absolute paths. If the $folderPath is below the $homeFolder, then the $folderPath string will start with and contain the entire $homeFolder string. If this is the case, we just glob all directories in the $folderPath and return their absolute pathes in an array.
To get the relative path of the $folderPath from the $homeFolder, just do
ltrim(str_replace('/home/gordon/', './', '/home/gordon/code/php/'), '/');
which would return ./code/php/.
If you want to do this with OOP, you might be interested in the SPL DirectoryIterator.

Creating a file inside a folder that doesn't exist yet in php

I want my php script to create an output file in a folder based on the date. The way I'm doing this is that its supposed to get the foldername/filename from a text file outputted by another program which I am unable to edit.
So the file its grabbing the data from looks like this:
data/newfolder/10302008/log_for_Today.txt | 24234234
Only with multiple lines, I just need the script to go through it line by line, grab the folder/filename and create an empty file with that name in that location.
The directories are all 777. Now I know how to create a new empty exe file in a folder but can't seem to figure out how to create the folder first then the exe inside of it, any ideas?
if(!file_exists(dirname($file)))
mkdir(dirname($file), 0777, true);
//do stuff with $file.
Use the third parameter to mkdir(), which makes it create directories recursively.
With
$directories = explode( '/', $path );
you can split the path to get single directory names. Then go through the array and create the directories setting chmod 777. (The system user, who executes php must have the ability to do that.)
$file = array_pop( $directories );
$base = '/my/base/dir';
foreach( $directories as $dir )
{
$path = sprintf( '%s/%s', $base, $dir )
mkdir( $path );
chmod( $path, 777 );
$base = $path;
}
// file_put_contents or something similar
file_put_contents( sprintf( '%s/%s', $base, $file ), $data );
The problem here is that you might not set chmod from your php script.
An alternative could be to use FTP. The user passes FTP login data to the script and it uses FTP functionality to manage files.
http://www.php.net/FTP
It's little too late but I found this question and I have a solution for this, here is an example code and it works good for me no matter how deep is your file. You should change directory separator for lines 1 and 3 if you're running it on Windows server.
$pathToFile = 'test1/test2/test3/test4/test.txt';
$fileName = basename($pathToFile);
$folders = explode('/', str_replace('/' . $fileName, '', $pathToFile));
$currentFolder = '';
foreach ($folders as $folder) {
$currentFolder .= $folder . DIRECTORY_SEPARATOR;
if (!file_exists($currentFolder)) {
mkdir($currentFolder, 0755);
}
}
file_put_contents($pathToFile, 'test');
Best regards, Georgi!
Create any missing folders using mkdir(), then create the empty file using touch().
You can use absolute paths in both cases, meaning:
mkdir('data');
mkdir('data/newfolder');
mkdir('data/newfolder/10302008');
touch('data/newfolder/10302008/log_for_Today.txt');
if you're curious about where it's starting-point it will be, you can use getcwd() to tell you the working directory.
Can't you just do this by creating the dir with mkdir (http://nl.php.net/manual/en/function.mkdir.php) then chmod it 777 (http://nl.php.net/manual/en/function.chmod.php) the change directory with chdir (http://nl.php.net/manual/en/function.chdir.php) and then create the file (touch)?

Categories