I have uploaded a lot of images from the website, and need to organize files in a better way.
Therefore, I decide to create a folder by months.
$month = date('Yd')
file_put_contents("upload/promotions/".$month."/".$image, $contents_data);
after I tried this one, I get error result.
Message: file_put_contents(upload/promotions/201211/ang232.png): failed to open stream: No such file or directory
If I tried to put only file in exist folder, it worked. However, it failed to create a new folder.
Is there a way to solve this problem?
file_put_contents() does not create the directory structure. Only the file.
You will need to add logic to your script to test if the month directory exists. If not, use mkdir() first.
if (!is_dir('upload/promotions/' . $month)) {
// dir doesn't exist, make it
mkdir('upload/promotions/' . $month);
}
file_put_contents('upload/promotions/' . $month . '/' . $image, $contents_data);
Update: mkdir() accepts a third parameter of $recursive which will create any missing directory structure. Might be useful if you need to create multiple directories.
Example with recursive and directory permissions set to 777:
mkdir('upload/promotions/' . $month, 0777, true);
modification of above answer to make it a bit more generic, (automatically detects and creates folder from arbitrary filename on system slashes)
ps previous answer is awesome
/**
* create file with content, and create folder structure if doesn't exist
* #param String $filepath
* #param String $message
*/
function forceFilePutContents ($filepath, $message){
try {
$isInFolder = preg_match("/^(.*)\/([^\/]+)$/", $filepath, $filepathMatches);
if($isInFolder) {
$folderName = $filepathMatches[1];
$fileName = $filepathMatches[2];
if (!is_dir($folderName)) {
mkdir($folderName, 0777, true);
}
}
file_put_contents($filepath, $message);
} catch (Exception $e) {
echo "ERR: error writing '$message' to '$filepath', ". $e->getMessage();
}
}
i have Been Working on the laravel Project With the Crud Generator and this Method is not Working
#aqm so i have created my own function
PHP Way
function forceFilePutContents (string $fullPathWithFileName, string $fileContents)
{
$exploded = explode(DIRECTORY_SEPARATOR,$fullPathWithFileName);
array_pop($exploded);
$directoryPathOnly = implode(DIRECTORY_SEPARATOR,$exploded);
if (!file_exists($directoryPathOnly))
{
mkdir($directoryPathOnly,0775,true);
}
file_put_contents($fullPathWithFileName, $fileContents);
}
LARAVEL WAY
Don't forget to add at top of the file
use Illuminate\Support\Facades\File;
function forceFilePutContents (string $fullPathWithFileName, string $fileContents)
{
$exploded = explode(DIRECTORY_SEPARATOR,$fullPathWithFileName);
array_pop($exploded);
$directoryPathOnly = implode(DIRECTORY_SEPARATOR,$exploded);
if (!File::exists($directoryPathOnly))
{
File::makeDirectory($directoryPathOnly,0775,true,false);
}
File::put($fullPathWithFileName,$fileContents);
}
I created an simpler answer from #Manojkiran.A and #Savageman. This function can be used as drop-in replacement for file_put_contents. It doesn't support context parameter but I think should be enough for most cases. I hope this helps some people. Happy coding! :)
function force_file_put_contents (string $pathWithFileName, mixed $data, int $flags = 0) {
$dirPathOnly = dirname($pathWithFileName);
if (!file_exists($dirPathOnly)) {
mkdir($dirPathOnly, 0775, true); // folder permission 0775
}
file_put_contents($pathWithFileName, $data, $flags);
}
Easy Laravel solution:
use Illuminate\Support\Facades\File;
// If the directory does not exist, it will be create
// Works recursively, with unlimited number of subdirectories
File::ensureDirectoryExists('my/super/directory');
// Write file content
File::put('my/super/directory/my-file.txt', 'this is file content');
I wrote a function you might like. It is called forceDir(). It basicaly checks whether the dir you want exists. If so, it does nothing. If not, it will create the directory. A reason to use this function, instead of just mkdir, is that this function can create nexted folders as well.. For example ('upload/promotions/januari/firstHalfOfTheMonth'). Just add the path to the desired dir_path.
function forceDir($dir){
if(!is_dir($dir)){
$dir_p = explode('/',$dir);
for($a = 1 ; $a <= count($dir_p) ; $a++){
#mkdir(implode('/',array_slice($dir_p,0,$a)));
}
}
}
Related
I have a Laravel Controller Function file_fetch()
public function file_fetch(Request $request) {
$file = request('routename');
$destinationPath = public_path('/folder/'.$file);
if(!File::exists($destinationPath)){
$content = File::get($destinationPath);
return view('filefetch', compact('file','content'));
}
else {
return redirect('/')->witherrormessage('NO such File Exists');
}
}
This works if i check for file public/folder/app/index.html and if i check for public/newfolder (newfolder doesnt exist) and hence it executes else function and redirects with error message, but if i search for public/folder/app/ I havent specified the file name, but the directory exists, hence the if(!File::exists($destinationPath)) function is getting executed!
i want to check just and files inside the directory and even if the directory exists, if file is not present, throw a error message, saying file doesnt exists.
add one more additional condition to check given path is file but not a directory
public function file_fetch(Request $request) {
$file = request('routename');
$destinationPath = public_path('/folder/'.$file);
if(!File::exists($destinationPath) && !is_dir($destinationPath)){
$content = File::get($destinationPath);
return view('filefetch', compact('file','content'));
}
else {
return redirect('/')->witherrormessage('NO such File Exists');
}
}
You can probably fix your code by validating the routename input such that it will never be empty (and have a certain file extension maybe?)
, which is nice to do anyhow.
If that fails, you can try File::isDirectory($dir) which basically calls is_dir(...).
Note that it might give you more control on your storage solution if you use the Storage::disk('public') functionalities from Laravel. The API is a bit different but there's a wide range of probabilities associated with it. Read more about that here: https://laravel.com/docs/8.x/filesystem#introduction.
If you in different/multiple buckets.
//Do not forget to import
use Illuminate\Support\Facades\Storage;
if (Storage::disk('s3.bucketname')->exists("image1.png")) {
}
Im building an application where I need to dynamically create some directories using the Azure's PHP SDK.
I did it using a loop but Im unsure if thats the correct way of doing it so heres my code;
I cant create a path that already exists so I have to check level by level if a directory and exists, than enters it and repeat.
public function generateDirectory($path)
{
$pathArray = explode("/", $path);
$currentPath = "";
try {
foreach ($pathArray as $key => $slice) {
$directories = $this->fileClient->listDirectoriesAndFiles("abraco", $currentPath)->getDirectories();
$currentPath .= $slice . "/";
$exists = false;
foreach ($directories as $key => $directory) {
if ($directory->getName() === $slice) {
$exists = true;
break;
}
}
if (!$exists) {
$this->fileClient->createDirectory("abraco", $currentPath);
}
}
return true;
} catch (Exception $e) {
return false;
}
}
Doesnt it should have a method to create a full path with subfolders? I think that this way is not performatic.
Doesnt it should have a method to create a full path with subfolders? I think that this way is not performatic.
I agree with you that there is a method to create a full path with subfolders will be better.
But currently, as you metioned that if we want to create full path with subfolders, we need to create the directory folder level by level.
If you use fiddler to capture request while you create multi-level directory structure via PHP SDK,you could find it use the following Rest API
https://myaccount.file.core.windows.net/myshare/myparentdirectorypath/mydirectory?
restype=directory
For more information please refer to Azure file Storage Create directory API.
myparentdirectorypath Optional. The path to the parent directory where mydirectory is to be created. If the parent directory path is omitted, the directory will be created within the specified share.
If specified, the parent directory must already exist within the share before mydirectory can be created.
I have a AWS EC2 server with phpMyAdmin to manage it.
Everything is working correctly but I would like to be able to create another folder in the /var/www/html directory to add files..
This is my code but it just keeps returning the error to me! any ideas??
// STEP 2.2 Create a folder in server to store posts'pictures
$folder = "/var/www/html/bloggerFiles/Posts/" . $id;
if(!file_exists($folder)){
if (!mkdir($folder, 0777, true)) {//0777
die('Failed to create folders...');
}
}
I would normally create that folder in the terminal by using sudo mkdir, but when I add sudo Nothing works!
Any help is appreciated!
Thanks in advance.
Make sure the folder(s) you are accessing are set to read and write folder permissions, then use this function:
function newFolder($path, $perms)
$path = str_replace(' ', '-', $path);
$oldumask = umask(0);
mkdir($path, $perms); // or even 01777 so you get the sticky bit set (0777)
umask($oldumask);
return true;
}
This fixed it for me.
You can create new folder doing this: newFolder('PathToFolder/here', 0777);
EDIT: Please have a look at: https://www.youtube.com/watch?v=7mx2XOFBp8M
EDIT: Also have a look at http://php.net/manual/en/function.mkdir.php#1207
EDIT: Storing functions in classes and safely use the function
class name_here
{
public function newFolder($path, $perms, $deny_if_folder_exists){
$path = 'PATH_TO_POSTS/'.$path; // This is for setting the root to PATH TO POSTS
$path = str_replace('../', '', $path); // Deny the path to go out of var/www/html/PATH_TO_POSTS/$path
if( $deny_if_folder_exists === true ){
if(file_exists($path)){return false;}
$old_umask = umask(0);
mkdir($path, $perms);
umask($old_umask);
}elseif( $deny_if_folder_exists === false ){
$old_umask = umask(0);
mkdir($path, $perms);
umask($old_umask);
}else{
return false; // Unknown
}
}
}
/* Call the function by doing this: */
$manage = new name_here;
$manage->newFolder('test', 777, true); // Test will appear in /var/www/html/PATH_TO_POSTS/$path, but if the folder exists it will return false and not create the folder.
EDIT: If this file is called from html it will re create the path, so I will it has to be called from /html/
EDIT: How to use the name_here class
/*
How to call the function?
$manage = new name_here; Creates a variable to an object (The class)
$manage->newFolder('FolderName', 0777, true); // Will create a folder to the path,
but this fill needs to be called from the html the root directory is set to the
"PATH_TO_POSTS/" basicly means you cannot do this function from "html/somewhere/form.php",
UNLESS the "PATH_TO_POSTS" is in the same directory as form.php
*/
I have a simple open (file) method which should throw an exception if it fails to open or create a file in the given path:
const ERR_MSG_OPEN_FILE = 'Failed to open or create file at %s';
public function open($filePath)
{
ini_set('auto_detect_line_endings', TRUE);
if (false !== ($this->handler = #fopen($filePath, 'c+'))) {
return true;
} else {
throw new \Exception(
sprintf(self::ERR_MSG_OPEN_FILE, $filePath)
);
}
}
There is unit-test around it using PHPUnit and VFSStream:
$structure = [
'sample.csv' => file_get_contents(__DIR__ . '/../sampleFiles/small.csv')
];
$this->root = vfsStream::setup('exampleDir', null, $structure);
$existingFilePath = vfsStream::url('exampleDir') . DIRECTORY_SEPARATOR . 'sample.csv';
$this->file = new File();
$this->file->open($existingFilePath);
The above setup creates a virtual directory structor containing a mock file (read/cloned from an existing CSV file) and this satisfy the open method's requirement to open a file. And also if I pass a different path (none existing file) it will be created in the same virtual structor.
Now in order to cover the exception I want to add a ready-only directory to the existing structor, lets say a folder belong to another user and I don't have write permission on it, like this when I try to open a non existing file in that folder, attempt to creating one should fail and the open method should throw the exception.
The only problem is,.... I don't know how to do it :D
Any Advice, hint and guidance will be appreciated :)
You could simply point your mock directory's url to an incorrect path.
$existingFilePath = vfsStream::url('badExampleDir') . DIRECTORY_SEPARATOR . 'incorrect.csv';
considering the badExampleDir never been setup your method will fail to create the file in it.
Im trying to Delete ALL Text files from a directory using a php script.
Here is what I have tried.....
<?php array_map('unlink', glob("/paste/*.txt")); ?>
I dont get an Error when I run this, yet It doesnt do the job.
Is there a snippet for this? Im not sure what else to try.
Your Implementation works all you need to do is use Use full PATH
Example
$fullPath = __DIR__ . "/test/" ;
array_map('unlink', glob( "$fullPath*.log"))
I expanded the submitted answers a little bit so that you can flexibly and recursively unlink text files located underneath as it's often the case.
// #param string Target directory
// #param string Target file extension
// #return boolean True on success, False on failure
function unlink_recursive($dir_name, $ext) {
// Exit if there's no such directory
if (!file_exists($dir_name)) {
return false;
}
// Open the target directory
$dir_handle = dir($dir_name);
// Take entries in the directory one at a time
while (false !== ($entry = $dir_handle->read())) {
if ($entry == '.' || $entry == '..') {
continue;
}
$abs_name = "$dir_name/$entry";
if (is_file($abs_name) && preg_match("/^.+\.$ext$/", $entry)) {
if (unlink($abs_name)) {
continue;
}
return false;
}
// Recurse on the children if the current entry happens to be a "directory"
if (is_dir($abs_name) || is_link($abs_name)) {
unlink_recursive($abs_name, $ext);
}
}
$dir_handle->close();
return true;
}
You could modify the method below but be careful. Make sure you have permissions to delete files. If all else fails, send an exec command and let linux do it
static function getFiles($directory) {
$looper = new RecursiveDirectoryIterator($directory);
foreach (new RecursiveIteratorIterator($looper) as $filename => $cur) {
$ext = trim($cur->getExtension());
if($ext=="txt"){
// remove file:
}
}
return $out;
}
i have modified submitted answers and made my own version,
in which i have made function which will iterate recursively in current directory and its all child level directories,
and it will unlink all the files with extension of .txt or whatever .[extension] you want to remove from all the directories, sub-directories and its all child level directories.
i have used :
glob() From the php doc:
The glob() function searches for all the pathnames matching pattern
according to the rules used by the libc glob() function, which is
similar to the rules used by common shells.
i have used GLOB_ONLYDIR flag because it will iterate through only directories, so it will be easier to get only directories and unlink the desired files from that directory.
<?php
//extension of files you want to remove.
$remove_ext = 'txt';
//remove desired extension files in current directory
array_map('unlink', glob("./*.$remove_ext"));
// below function will remove desired extensions files from all the directories recursively.
function removeRecursive($directory, $ext) {
array_map('unlink', glob("$directory/*.$ext"));
foreach (glob("$directory/*",GLOB_ONLYDIR) as $dir) {
removeRecursive($dir, $ext);
}
return true;
}
//traverse through all the directories in current directory
foreach (glob('./*',GLOB_ONLYDIR) as $dir) {
removeRecursive($dir, $remove_ext);
}
?>
For anyone who wonder how to delete (for example: All PDF files under public directory) you can do this:
array_map('unlink', glob( public_path('*.pdf')));