I am attempting to write a PHP script that organizes uploaded files into directories according to the date they were uploaded. The script needs to detect whether or not the appropriate directories exists before it executes the upload. First, it checks if the folder 'attachments/2014' exists. If it doesn't, it's created. Next, it checks if the folder 'attachments/2014/October" exists. If it doesnt, create it. Finally, it checks if the folder 'attachments/2014/October/29' exists. If it doesnt, it's created. Then the file is uploaded to the last folder.
For some reason, my script always tries to create the directory, even if it already exists. It only works if the directory doesn't exist. Not really sure why about the former. This is CodeIgniter PHP.
$dtree = array(
date('Y'),
date('Y').'/'.date('F'),
date('Y').'/'.date('F').'/'.date('d')
);
$this->load->library('ftp');
$this->ftp->connect();
foreach($dtree as $dir) {
if($this->ftp->list_files('attachments/'.$dir)) === FALSE) {
$this->ftp->mkdir('attachments/'.$dir);
}
}
If the directory exists, I get the CI error saying "Unable to create the directory you have specified."
Related
I have some encrypted responses that I convert to a Zip file in my Laravel application. The function below downloads the API response, saves it as a Zip file, and then extracts it while I read the folder's contents. In my local environment, it works well. However, the Zip file is not getting saved to the storage folder on the live server. No error is being shown, only an empty JSON response. Please, what could be the cause?
public function downloadZipAndExtract($publication_id, $client_id)
{
/* We need to make the API call first */
$url = $this->lp_store."clients/$client_id/publications/$publication_id/file";
$file = makeSecureAPICall($url, 'raw');
// Get file path. If file already exist, just return
$path = public_path('storage/'.$publication_id);
if (!File::isDirectory($path)) {
Storage::put($publication_id.'.zip', $file);
// Zip the content
$localArchivePath = storage_path('app/'.$publication_id.'.zip');
$zip = new ZipArchive();
if (!$zip->open($localArchivePath)) {
abort(500, 'Problems experienced while reading file.');
}
// make directory with the publication_id
// then extract everything to the directory
Storage::makeDirectory($publication_id);
$zip->extractTo(storage_path('app/public/'.$publication_id));
// Delete the zip file after extracting
Storage::delete($publication_id.'.zip');
}
return;
}
First thing I'd check is if the storage file is created and if it isn't created, create it. Then I'd look at your file permissions and make sure that the the groups and users permissions are correct and that you aren't persisting file permissions on creation. I've had many instances where the process that's creating files(or trying) is not in the proper group and there is a sticky permission on the file structure.
I've got a web form which has a unique upload folder for each user (using their PHP session_id() as the folder name) which works well. When the form is submitted (after error checking) PHPMailer is used to send the email and the attachments. This is also working well. However, after the email is sent, I would like to remove the uploads from the folder and then the folder itself (sort of a self-cleanup!) The files are removed as expected but the folder remains (albeit empty). I wonder if the folder is somehow "still in use" so doesn't get deleted or something similar? This is the code:
// Empty the contents of the upload folder
if (is_dir($dir)) { // Target directory ($dir) is set above in photos POST section
// Check for any files inside the directory
$files = glob($dir.'/*'); // Get all file names
foreach($files as $file) { // Iterate through the files
if(is_file($file)) { // Check its a file
unlink($file); // Delete the file
}
}
// Remove the upload folder
rmdir($dir); //NOT WORKING? NEEDS SOME TROUBLESHOOTING...
}
Any other ideas on why this folder is remaining?
Ben
I would guess that your folders might contain hidden files (starting with .) which the default glob pattern won't match, so try this:
$files = glob($dir . '/{,.}*'); // Get all file names including hidden ones
foreach($files as $file) { // Iterate through the files
if(is_file($file)) { // Check its a file
unlink($file); // Delete the file
}
}
Also check the return value on both unlink and rmdir so you can see exactly where it's failing.
Turns out after much testing that the problem was not actually with rmdir at all! My web form uses a Dropzone for photo uploads to a unique folder for each user using their php session_id() and this folder is supposed to be created when they add a photo to Dropzone (if it doesn’t already exist). Problem was I’d put the folder creation code outside of the actual upload script so the folder was in fact being deleted but them instantly created again when the form submitted and the page reloads! Sorry about that but thanks for all your help. :)
I am creating directory in php with mkdir it returns true but when i ssh into my server i cannot find directory in specified path.
I have checked in different locations in server.
if (!file_exists('/tmp/tmpfileeee')) {
mkdir('/tmp/tmpfileeee',0755);
echo 'created';
}
Does tmp exist where this is executing? Is tmpfileee a file or directory you are trying to create? If tmp does not exist and neither does tmpfileee, I believe you are trying to make 2 directories without a recursive parameter in the call.
My PHP is definitely rusty so maybe someone else can answer better but that was just my initial thoughts looking at it.
Just try as that:
if (!file_exists('tmp/tmpfileeee') AND !is_dir('tmp/tmpfileeee')) {
mkdir('tmp/tmpfileeee',0755, true);
echo 'created';
}
mkdir creates a folder not file.
If you want to create an file:
if (!file_exists('tmp/tmpfileeee') AND !is_file('tmp/tmpfileeee')) {
$fp = fopen('tmp/tmpfileeee', 'w');
echo 'created';
}
or best way:
// 1. Check folder and xreate if not exists
if (!file_exists('tmp') AND !is_dir('tmp')) {
mkdir('tmp',0755, true);
echo 'folder created';
}
// 2. Check file and create if not exists
if (!file_exists('tmp/tmpfileeee') AND !is_file('tmp/tmpfileeee')) {
$fp = fopen('tmp/tmpfileeee', 'w');
echo 'file created';
}
UPDATE
On some servers, the tmp and temp folders are restricted.
Check for open_basedir.
PHP manual states:
If the directory specified here is not writable, PHP falls back to the system default temporary directory. If open_basedir is on, then the system default directory must be allowed for an upload to succeed.
Quick question. I'll start off with an example.
I have a social site similar to Facebook. When a user signs up my PHP script creates a directory named after his username and a custom sub-directory for this user called "photos".
The "photos" directory is never created when someone signs up. I assume it is because the actual server hasn't created the actual username directory in the first place.
My solution is that anytime i need to execute the photo function on my site for a user I should check if the folder exists and if not create it, which works fine. Is this standard procedure? Or is there a better way to create multiple directories at the same time while running checks.
When someone signs up I run this code, and the latter if statement doesn't successfully create the photos folder, so i check these two statements anytime I am editing something that would go in photos as a check for if the folder exists.
if (!file_exists("user/$username")) {
mkdir("user/$username", 0755);
}
if (!file_exists("user/$username/photos"))
{
mkdir("user/$username/photos", 0755);
}
The directories are created sequentially/synchronously thus once execution of the first mkdir() is finished the folder should be there with the indicated permission set.
As stated here the mkdir()
Returns TRUE on success or FALSE on failure.
and
Emits an E_WARNING level error if the directory already exists.
Emits an E_WARNING level error if the relevant permissions prevent
creating the directory.
So you can go:
if (!file_exists("user/$username")) {
if(mkdir("user/$username", 0755))
{
//directory created
if (!file_exists("user/$u/photos"))
{
mkdir("user/$username/photos", 0755);
}
}
else
{
//directory not created
}
}
If the mkdir() returns false - check the logs or handle the error.
You can do a quick directory 'exists' check like this
function check($images_dir) {
if($handle = opendir($images_dir)) {
// directory exists do your thing
closedir($handle);
} else {
// create directory
}
}
Where $images_dir = path/directory/user/$username
I was fiddling with my code, trying to write some code that will take data(including pictures) uploaded from a form via POST which will then create a directory complete with its associated subdirectories to store the image.
While writing the code, i kept getting the error
Warning: mkdir(): No such file or directory in C:\Users\Admin\Desktop\UniServer\www\AddItem.php on line 94
HOWEVER, when i set mkdir's resursion to true, mkdir suddenly works and the directory is created without any problems.
My Code:
if(isset($_FILES['upload']['tmp_name']))
{
$numfile=count($_FILES['upload']['tmp_name']);
{
for($i=0;$i<$numfile;$i++)
{
if(is_uploaded_file($_FILES['upload']['tmp_name'][$i]))
{
//Conditionals for uploaded file
$foldername=$_SESSION['UserId'];
$cat=$_POST['category'];
$sub=$_POST['subcat'];
$itemname=$_POST['itemname'];
$allowed_filetypes=array('.jpg','.gif','.bmp','.png');
$max_filesize = 2097152; // Maximum filesize in BYTES (currently 2.0MB).
$upload_path = 'C:\Users\Admin\Desktop\UniServer\www\images\\'.$foldername.'\\'.$cat.'\\'.$sub.'\\'.$itemname.'\\'; // The place the files will be uploaded to.
//Checks if Folder for User exists
//If not, A folder for the user is created to store the user's images
if(!file_exists($upload_path))
{
$upload_path=mkdir($upload_path,0644,true);<-- This is the line
}
$filename = $_FILES['upload']['name'][$i]; // Get the name of the file (including file extension).
$ext = substr($filename, strpos($filename,'.'), strlen($filename)-1); // Get the extension from the filename.
// Check if the filetype is allowed, if not DIE and inform the user.
if(!in_array($ext,$allowed_filetypes))
{
die('The file you attempted to upload is not allowed.');
}
// Now check the filesize, if it is too large then DIE and inform the user.
if(filesize($_FILES['upload']['tmp_name'][$i]) > $max_filesize)
{
die('The file you attempted to upload is too large.');
}
// Check if we can upload to the specified path, if not DIE and inform the user.
if(!is_writable($upload_path))
{
$errormsg="Image Upload Failed.";
}
if(!move_uploaded_file($_FILES['upload']['tmp_name'][$i],"$upload_path" . $filename))
{
$errormsg= 'Your file upload was successful, view the file here'; // It worked.
}
}
}
}
}
else{echo"Upload failed";}
While my code is working now that i've set recursion to true, i still DON't understand exactly WHY it is working, so i would really appreciate it if someone could explain why exactly my code is working.
The closest i've come is with Why mkdir fails with recursive option set true?
Though i couldnt understand any of what was said in the link.
Thanks!
The mkdir() needs the recursive set to true since you ask it to create nested directories that do not exist, i.e.:
$upload_path = 'C:\Users\Admin\Desktop\UniServer\www\images\\'.$foldername.'\\'.$cat.'\\'.$sub.'\\'.$itemname.'\\';
So since the variable $foldername gets its value from the user session, if the user session change it changes. The same goes for the rest of the $upload_path parts, if something of them changes you have to create the whole path. Only the last part of the path ($itemname) can change without using the recursive option.
It fails because it parses the path provided as argument and "changes" path to parent of new directory.
Try this (in a folder test with a subfolder s):
mkdir s/s2/s3 <- will fail because s2 does not exist in s
mkdir s/s2 <- ok
mkdir s/s2/s3 <- ok
When calling with recursive set to TRUE, it does something different: splits the path as usual, but checks existence of each prefix.
Again in folder test:
mkdir -p s/s1/s2/s3/s4 will yield the following prefixes:
s
s/s1
s/s1
s/s1/s2
s/s1/s2/s3
s/s1/s2/s3/s4
Note: I've used mkdir under linux and p argument tells it to create parent directories if they do not exist (same as recursive).