This question already has answers here:
PHP - Failed to open stream : No such file or directory
(10 answers)
Closed 6 years ago.
I am creating a profile picture upload function for my site, but for some reason, move_uploaded_file() does not want to function.
I have tried multiple forums and tested out all the possible different approaches, but with no luck.
Here is my PHP & HTML:
<?php
if(isset($_FILES['avatar'])){
if(empty($_FILES['avatar']['name'])){
$errors[] = 'Please select an avatar.';
} else {
$ext = array('jpg', 'jpeg', 'png');
$file = $_FILES['avatar']['name'];
$fileext = strtolower(end(explode('.', $file)));
$filetmp = $_FILES['avatar']['tmp_name'];
if(in_array($fileext, $ext)){
$file = md5(microtime() . $filetmp) . '.' . $fileext;
$filepth = './data/user_data/img/udid/prof/' . $file;
move_uploaded_file($filetmp, $filepth);
} else {
$errors[] = 'Please select a valid file type. (JPG, JPEG or PNG)';
}
}
}
?>
<form action="" method="post" class="avatar-form-form" enctype="multipart/form-data">
<input type="file" name="avatar"><br>
<input type="submit" value="Upload">
</form>
So first off, I am checking that the selected file has a valid extension, if so, it will hash the file temporary name with the microtime (for security). I am then concatenating the extension onto the end with a full stop between it, i.e the output will be md5hash.png.
I am then creating a file path variable by concatenating the file variable onto the end of my directory.
I then proceed with the file upload function by passing through the $filetmp and $filepth variables (like you're supposed to do).
However, when I go to test this function out on my page, I get these errors:
Warning: move_uploaded_file(./data/user_data/img/udid/prof/e4d0cde3c9330222ef3ab651fe797bed.jpg):
failed to open stream: Permission denied in /Applications/XAMPP/xamppfiles/htdocs/test/settings.php
on line 40
Warning: move_uploaded_file(): Unable to move '/Applications/XAMPP/xamppfiles/temp/phpkWSGLy'
to './data/user_data/img/udid/prof/e4d0cde3c9330222ef3ab651fe797bed.jpg'
in /Applications/XAMPP/xamppfiles/htdocs/test/settings.php
on line 40
This is my current layout:
The settings page (the one where the user uploads there picture) is in the root directory.
The location in which I want to put the avatar is inside of a folder (also in the root directory.
I am currently testing all of this on my MacBook running XAMPP and have made sure that file_uploads is set to "on" in my php.ini file.
All help is appreciated. Not sure If I have done this incorrectly, but I am almost certain that I haven't.
EDIT:
So, It turns out, that by default on a MacBook (when running XAMPP), all files inside of XAMPP/htdocs are set to read only and you must manually set them to "read & write" to allow move_uploaded_file to work.
Check that you have set the proper write permissions for your uploaded images folder in your MacBook.
Related
I'm following a tutorial for uploading image files using php on udemy. I can choose an image and upload it to a folder without any problems.
When I click on the image after it has been uploaded to the folder, windows photo viewer says: "photo.png It appears that you don't have permission to view this file. Check the permissions and try again".
When I checked permissions it said "You must have read permissions to view the properties of this file".
I used the chmod function set to 0755, which allows the owner to read and write, and lets everyone else read it. I tried changing the chmod codes but it didn't help.
I'm thinking it has something to do with my server permissions, but can't find any solution on google. My images are uploaded to Abyss Web Server.
Here is the code:
<?php
error_reporting(E_ALL);
ini_set('display_errors', 1);
function upload_file() {
//setup
$tmp_name = $_FILES['file']['tmp_name'];
$target_dir = 'uploads/';
$target_file = $target_dir . basename($_FILES['file']['name']);
$max_file_size = 5000000; //5mb
$allowed_file_types = array('application/pdf; charset=binary');
$allowed_image_types = array(IMAGETYPE_GIF, IMAGETYPE_JPEG, IMAGETYPE_PNG);
//check if image type is allowed
$image_check = getimagesize($tmp_name);
if(! in_array($image_check[2], $allowed_image_types)) {
//if not allowed image check if allowed file type
exec('file -bi' . $tmp_name, $file_check);
if(! in_array($file_check[0], $allowed_file_types)) {
return 'This file type is not allowed';
}
}
//check if file already exists
if(file_exists($target_file)) {
return 'Sorry that file already exists';
}
//check file size
if(file_exists($target_file)) {
return 'Sorry this file is too big';
}
//store the file
if(move_uploaded_file($tmp_name, $target_file)) {
chmod($target_file, 0644);
return 'Your file was uploaded';
}
else {
return 'There was a problem storing your file. Try again?';
}
}
if(! empty($_FILES)) {
echo upload_file();
}
?>
<form action="" method="post" enctype="multipart/form-data">
Select image to upload:
<input type="file" name="file">
<input type="submit" Value="upload">
</form>
Since loading the file using a custom made HTML page specifically for testing motives does show the image correctly, then it's most likely a hotlink protection issue. (This was found out after a few comments to the question).
In cPanel, for example, there is a tool to manage this feature and it revolves around the usage of a file called .htaccess. This file is used for a lot of things in the web development world.
Some people don't like their copyrighted images to be accessed, so one way to avoid inexperienced people (let's say, "people in userland") from doing that is to enable this protection. This works for any given file extension that you set it up to.
One way to address this issue is to go to cPanel and disable (or modify accordingly) the Hotlink Protection feature. Another way, is to find the .htaccess file that is causing the issue, which requires understanding the way it works and the syntax it uses.
Ok, I used google over the last 2 days and didn't got what is wrong with my code. First it seemed that I used the wrong path but the official "Hilfe Center" (like helping center or so) from 1&1 said that this must be the right path "e:\Kunden\Homepages\11\d12345678\www\UploadTest" (obviously you have to adapt it to your path, which i got throught phpinfo() )
so I'm using the following code:
<form action=\"upload.php\" method=\"post\" enctype=\"multipart/form-data\">
<input type=\"file\" name=\"datei\"><br>
<input style=\"position:absolute;left:5px\" type=\"submit\" value=\"Hochladen\">
</form>
on the site where you upload the file and
$max_filesize = 524288; // Maximum filesize in BYTES (currently 0.5MB).
$upload_path = "e:\\Kunden\\Homepages\\11\\d12345678\\www\\UploadTest";
$filename = $_FILES['userfile']['name']; // Get the name of the file (including file extension).
if(filesize($_FILES['userfile']['tmp_name']) > $max_filesize)
die('The file you attempted to upload is too large.'); // if we upload large file then we get error.
if(!is_writable($upload_path))
die('You cannot upload to the specified directory, please CHMOD it to 777.'); // if we have no enough permission then got error.
if(move_uploaded_file($_FILES['userfile']['tmp_name'],$upload_path . $filename)){
// if everything is fine then we upload file and go to somewhere else
header ('location: whereeveryouwantogo.php');
} else {
echo 'There was an error during the file upload. Please try again.';
}
on the site where the php script is running (upload.php). I got the code on another thread here and wanted to use it for troubleshooting. Later I'm going back to my own code.
I am now at the last error:
'There was an error during the file upload. Please try again.';
I just want to upload .txt files that are later used on a news based site. Thx for any helps in advance!
I think the problem is name of the input or name of the files variable.
$files=$_FILES['datei']['tmp_name'];
I have a very basic, very straightforward function that takes a file (after checking it to make sure its a zip among other things) and uploads it, unpacks it and such:
public function theme(array $file){
global $wp_filesystem;
if(is_dir($wp_filesystem->wp_content_dir() . "/themes/Aisis-Framework/custom/theme/")){
$target_path = $wp_filesystem->wp_content_dir() . "/themes/Aisis-Framework/custom/theme/";
if(move_uploaded_file($file['tmp_name'], $target_path . '/' . $file['name'])) {
$zip = new ZipArchive();
$x = $zip->open($target_path);
if ($x === true) {
$zip->extractTo($target_path); // change this to the correct site path
$zip->close();
//unlink($target_path);
}
$this->success('We have uplaoded your new theme! Activate it bellow!');
} else {
$this->error('Oops!', 'Either your zip is corrupted, could not be unpacked or failed to be uploaded.
Please try again.');
}
}else{
$this->error('Missing Directory', 'The Directory theme under custom in Aisis Theme does not exist.');
}
if(count(self::$_errors) > 0){
update_option('show_errors', 'true');
}
if(count(self::$_messages) > 0){
update_option('show_success', 'true');
}
}
Extremely basic, yes I have used my target path as both the path to upload too and unpack (should I use a different path, by default it seems to use /tmp/tmp_name)
Note: $file is the array of $_FILES['some_file'];
My question is I get:
Warning: move_uploaded_file(/var/www/wordpress/wp-content//themes/Aisis-Framework/custom/theme//newtheme.zip): failed to open stream: Permission denied in /var/www/wordpress/wp-content/themes/Aisis-Framework/CoreTheme/FileHandling/Upload/Upload.php on line 82
Warning: move_uploaded_file(): Unable to move '/tmp/phpfwechz' to '/var/www/wordpress/wp-content//themes/Aisis-Framework/custom/theme//newtheme.zip' in /var/www/wordpress/wp-content/themes/Aisis-Framework/CoreTheme/FileHandling/Upload/Upload.php on line 82
Which basically means that "oh the folder your trying to move from is owned by root, no you cannot do that." the folder I am moving too is owned by apache, www-data. - I have full read/write/execute (it's localhost).
So question time:
Should my upload to and move to folder be different?
How, in a live environment, because this is a WordPress theme, will users who have the ability to upload files be able to get around this "you dont have permission"?
You should try to do it the wordpress way. Uploading all user content to wp-content/uploads, and doing it with the native functions.
As you mention, uploading to a custom directory, may be an issue to non tech savvy users. /uploads already have the special permissions.
Check out wp_handle_upload. You just have to limit the mime type of the file.
The path you are trying to upload is some where wrong here
wp-content//themes
try removing one slash
Okay, so I set up an upload engine for a website so that an authenticated user can upload a audio file (a key) for a song in the library, but I come across this strange problem when I try to upload any file over 5MB.
I set my php.ini max filesize to 50MB by the way
Everything uploads properly, but there is no data associated with the file on the other end.
HTML CODE:
<form action="keyUpload.php?id=<?php echo $id;?>" method="post" enctype="multipart/form-data">
<p style="color:#fff;font-size:30px;font-family:Times">
Add a new Key:<br/><input name="uploaded" type="file" id="file"><br />
<input type="text" name="kname" id="kname" value placeholder="Key Name (Ex. Demo, A#, etc.)" style="width:300px;"><br/>
<button class="button">Upload File</button><br/>
<span style="font-size:12px;">*Max Filesize is 50 MB*</span>
</p>
</form>
PHP CODE:
<?php
$id=$_GET["id"];
$name=$_POST["kname"];
$name = str_replace(" ","%20",$name);
$allowed_filetypes = array('.mp3','.m4a','.wav','.wma');
$filename = $_FILES['uploaded']['name'];
$ext = substr($filename, strpos($filename,'.'), strlen($filename)-1);
Both $filename and $ext are empty variables when I upload a file larger than 5 MB. In all other cases, this engine works perfectly.
When echoed, simply nothing happens, so obviously the engine will not save the file if it doesn't exist. What's going on?
var_dump:
array(0) { }
Thanks for all your help!
Check for upload errors:
if ($_FILES['uploaded']['error'] !== UPLOAD_ERR_OK) {
die("Upload failed with error code " . $_FILES['uploaded']['error']);
}
The error codes are defined here: http://www.php.net/manual/en/features.file-upload.errors.php
As well, do NOT use filenames to validate the uploads. It is beyond trivial for a malicious user to fake a filename and upload malicious files, eg.
ren nastyvirus.exe good_tune.mp3
And don't use string operations on filenames. There's a whole whack of PHP functions for filename manipulation, e.g. http://php.net/basename
Set max_post_size in php.ini as well.
I am sending image from android apps to server. The problem is image not moving to the correct path, but only at current directory (only in which that php script stored). I tested this codes on local server and webserver, getting same result. Any one can find out whats problems.
Local Server: XAMPP 1.7.7
My PHP Script :
<?php
$base=$_REQUEST['image'];
$Username=$_REQUEST['Username'];
$binary=base64_decode($base);
header('Content-Type: bitmap; charset=utf-8');
$file = fopen($Username.'.png', 'w');
fwrite($file, $binary);
$uploadFilename = '/htdocs/android/ProfileImage/';
$tr =move_uploaded_file($_FILES[$file]['tmp_name'], $uploadFilename);
if($tr)
echo 'true';
else
echo 'false';
echo 'Successfully Uploaded';
?>
Showing Output and Error in Local Server
Strict Standards: Resource ID#3 used as offset, casting to integer (3) in C:\xampp\htdocs\android\uploadSimage.php on line 12
Notice: Undefined offset: 3 in C:\xampp\htdocs\android\uploadSimage.php on line 12
falseSuccessfully Uploaded
Showing Output and Error in Webserver
Notice: Undefined offset: 3 in C:...\uploadSimage.php on line 12
falseSuccessfully Uploaded
move_uploaded_file() expects the second parameter to be a string representing the new path and filename of upload. Currently, you are passing only a path. I also question whether the path is correct. It must be a full path, or a relative path.
You are also using the $_FILES array incorrectly. Are you uploading the image by encoding it in base64 and passing it via the URL's query string? Or are you actually uploading it using a multipart/form-data file upload field?
If you uploaded a file belonging to the upload field called image then you would get access to the file like this:
$origname = $_FILES['image']['name']; // the name from the client device
$temppath = $_FILES['image']['tmp_name']; // the temp location on the PHP server
$error = $_FILES['image']['error']; // > 0 if there was an error
$size = $_FILES['image']['size']; // size of the file
$type = $_FILES['image']['type']; // mime type, cannot be trusted though
You would then move it like this:
// Be careful using the original file name.
// If the user uploads a file with a .php extension, they may be
// able to run PHP code on your server if they can access the upload folder
// You should either generate a random file name or remove the extension
// IF THE DESTINATION FILE EXISTS, IT WILL BE OVERWRITTEN
$newPath = '/home/yoursite/htdocs/uploads/' . $origname;
$moved = move_uploaded_file($_FILES['image']['tmp_name'], $newPath);
if ($moved) {
echo "File was moved successfully.";
} else {
echo "Failed to move file.";
}
EDIT:
If you are in fact uploading the image by encoding it in base64 and sending it over the URL, then you don't need move_uploaded_file at all; in that case you can just write the decoded contents to a file anywhere you like. Keep in mind, the length of the URL may be limited so sending the image in the URL via base64 may not be a good idea.
EDIT 2:
To comment on the questions in your subsequent answer: The php function move_uploaded_file() should only be used when the file you are trying to move was uploaded to PHP using an HTTP POST method upload. It does an internal check to see if the file you are trying to move was uploaded to PHP. If it was not, then it won't move the file. Therefore you shouldn't be using move_uploaded_file() since you confirmed you were uploading the image through the URL.
Since your PHP script's path is C:\xampp\htdocs\android, this means the root path is C:\. The server root is different from your web root or document root which are both relative to your public directory. Any time you are dealing with reading/writing files in PHP, you use the full server path (relative to C:\ or /).
Given the new facts, try some code like this to "upload" the image:
<?php
$base = (isset($_REQUEST['image'])) ? $_REQUEST['image'] : '';
$Username = (isset($_REQUEST['Username'])) ? trim($_REQUEST['Username']) : '';
$binary = #base64_decode($base);
if (empty($Username)) {
die('no username specified');
}
if (!$binary) {
// data was not in base64 or resulted in an empty string
die('invalid image uploaded');
}
$basePath = 'C:\\xampp\\htdocs\\android\\ProfileImage\\';
$imagePath = $basePath . $Username . '.png';
$file = #fopen($imagePath, 'w+');
if (!$file) {
die('failed to open ' . $imagePath . ' for writing');
}
fwrite($file, $binary);
fclose($file);
echo 'Successfully Uploaded';
Make sure to take the necessary precautions so I can't upload an image for another user.
per to this document http://php.net/manual/en/function.move-uploaded-file.php another reason for this problem is invalid File name if your file Name in
move_uploaded_file ( string $filename , string $destination ) be invalid
this function return false
I accessed my server using file zilla and give write Group permissions to the target folder and then it worked.
If you're using XAMPP:
sudo chmod 777 -R /opt/lampp/htdocs/