PHP move_uploaded_file() error? - php

I using following code and it is successfully uploading files on my local machine. It is showing "Successfully uploaded" on my local machine.
// Upload file
$moved = move_uploaded_file($_FILES["file"]["tmp_name"], "images/" . "myFile.txt" );
if( $moved ) {
echo "Successfully uploaded";
} else {
echo "Not uploaded";
}
But when I used this code on my online server then it is not uploading file and just showing message "Not uploaded".
How can I know that what is the problem and how can I get the actual problem to display to the user ?

Edit the code to be as follows:
// Upload file
$moved = move_uploaded_file($_FILES["file"]["tmp_name"], "images/" . "myFile.txt" );
if( $moved ) {
echo "Successfully uploaded";
} else {
echo "Not uploaded because of error #".$_FILES["file"]["error"];
}
It will give you one of the following error code values 1 to 8:
UPLOAD_ERR_INI_SIZE =
Value: 1; The uploaded file exceeds the upload_max_filesize directive in php.ini.
UPLOAD_ERR_FORM_SIZE =
Value: 2; The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form.
UPLOAD_ERR_PARTIAL =
Value: 3; The uploaded file was only partially uploaded.
UPLOAD_ERR_NO_FILE =
Value: 4; No file was uploaded.
UPLOAD_ERR_NO_TMP_DIR =
Value: 6; Missing a temporary folder. Introduced in PHP 5.0.3.
UPLOAD_ERR_CANT_WRITE =
Value: 7; Failed to write file to disk. Introduced in PHP 5.1.0.
UPLOAD_ERR_EXTENSION =
Value: 8; A PHP extension stopped the file upload. PHP does not provide a way to ascertain which extension caused the file upload to stop; examining the list of loaded extensions with phpinfo() may help.

Try this:
$upload_dir = $_SERVER['DOCUMENT_ROOT'] . '/images/';
if (is_dir($upload_dir) && is_writable($upload_dir)) {
// do upload logic here
} else {
echo 'Upload directory is not writable, or does not exist.';
}
This will instantly flag any file permission errors.

Check that the web server has permissions to write to the "images/" directory

How can I know that what is the problem
Easy. Refer to the error log of the webserver.
how can I get the actual problem to display to the user ?
NEVER do it.
An average user will unerstand nothing of this error.
A malicious user should get no feedback, especially in a form of very informative error message.
Just show a page with excuses.
If you don't have access to the server's error log, your task become more complicated.
There are several ways to get in touch with error messages.
To display error messages on screen you can add these lines to the code
ini_set('display_errors',1);
error_reporting(E_ALL);
or to make custom error logfile
ini_set('log_errors',1);
ini_set('error_log','/absolute/path/tp/log_file');
and there are some other ways.
but you must understand that without actual error message you can't move. It's hard to be blind in the dark

move_uploaded_file() will return:
FALSE if file name is invalid
FALSE and issue a warning in the error log if the apache process does not have read/write permissions to source or destination directories
PHP Error Log
My php error log was at: /var/log/httpd/error_log and had these errors:
Warning: move_uploaded_file(images/robot.jpg): failed to open stream: Permission denied in /var/www/html/mysite/mohealth.php on line 78
Warning: move_uploaded_file(): Unable to move '/tmp/phpsKD2Qm' to 'images/robot.jpg' in /var/www/html/mysite/mohealth.php on line 78
move_uploaded_file() tries to move files from a temporary directory to a destination directory. When apache process tried to move files, it could not read the temporary or write to the destination dir.
Find which user is running Apache (Web Server)
Check which user is running the apache service by this command: ps aux | grep httpd. The first column is the user name.
Check Read Permission at Temporary Dir: Your can find the path to your temp dir by calling echo sys_get_tmp_dir(); in a php page. Then on the command line, issue ls -ld /tmp/temporary-dir to see if the apache user has access to read here
Check Write Permission at Destination Dir: issue ls -ld /var/www/html/destination-directory to see if the apache user has access to write here
Add permissions as necessary using chown or chgrp
Restart Apache using sudo service httpd restart

Do you checks that file is uploaded ok ? Maybe you exceeded max_post_size, or max_upload_filesize. When login using FileZilla you are copying files as you, when uploading by PHP wiritng this file is from user that runs apache (for exaplme www-data), try to put chmod 755 for images.

or run suexec and never have to change permissions again.

In php.ini search for upload_max_filesize and post_max_size. I had the same problem and the solution was to change these values to a value greater than the file size.

Please check that your form tag have this attribute:
enctype="multipart/form-data"

$uploadfile = $_SERVER['DOCUMENT_ROOT'].'/Thesis/images/';
$profic = uniqid(rand()).$_FILES["pic"]["name"];
if(is_uploaded_file($_FILES["pic"]["tmp_name"]))
{
$moved = move_uploaded_file($_FILES["pic"]["tmp_name"], $uploadfile.$profic);
if($moved)
{
echo "sucess";
}
else
{
echo 'failed';
}
}

On virtual hosting check your disk quota.
if quota exceed, move_uploaded_file return error.
PS : I've been looking for this for a long time :)

Please check permission "images/" directory

I ran into a very obscure and annoying cause of error 6.
After goofing around with some NFS mounted volumes, uploads started failing.
Problem resolved by restarting services
systemctl restart php-fpm.service
systemctl restart httpd.service

Related

Upload file through PHP is success up to 60MB , but browser cannot get response when file size bigger than 10MB

please ignore "Original" information since I already know this is nothing to do with CI.
In order to simplify problems, I create another vhost and put only one HTML and one PHP files, just to try pure file upload without CI.
<html><body>
<form method="post" enctype="multipart/form-data" action="upload.php">
<input type="file" name="my_file">
<input type="submit" value="Upload">
</form>
</body></html>
And pure file upload like this:
# Check if file uploaded
if ($_FILES['my_file']['error'] === UPLOAD_ERR_OK){
echo 'file name: ' . $_FILES['my_file']['name'] . '<br/>';
echo 'file type: ' . $_FILES['my_file']['type'] . '<br/>';
echo 'file size: ' . ($_FILES['my_file']['size'] / 1024) . ' KB<br/>';
echo 'tmp file: ' . $_FILES['my_file']['tmp_name'] . '<br/>';
# check if file exits
if (file_exists('/tmp/' . $_FILES['my_file']['name'])){
echo 'file already exists。<br/>';
} else {
$file = $_FILES['my_file']['tmp_name'];
$dest = '/tmp/after-' . $_FILES['my_file']['name'];
# try moving file and rename
move_uploaded_file($file, $dest);
}
} else {
echo 'Error:' . $_FILES['my_file']['error'] . '<br/>';
}
Upload file less than 10MB is fine, will receive echo message. But upload file larger than 10MB will receive no echo message. Check my /tmp folder can see upload is success. There is a "after-firewall.pdf.zip" file which is 21MB, so upload and move is done.
-rw-r--r-- 1 apache apache 21M 2月 9 07:25 after-firewall.pdf.zip
-rw-r--r-- 1 apache apache 420K 2月 9 07:31 after-LINE_ALBUM_230117_6.jpg
-rw-r--r-- 1 apache apache 8.1M 2月 9 07:24 after-test_upload.zip
-rw-r--r-- 1 apache apache 141 2月 9 06:50 upload_log.txt
But why browser and POSTMAN cannot get response? Is there any setting block or delay php-fpm or Apache2 response?
------------- Original Question ---------
You can ignore below complex statement....
We already know this is nothing to do with CodeIgniter.
We have an up and running services which using CodeIgniter 3.1.11. I am trying to add an upload file function and it works. But somehow if file is larger than 10MB, browser cannot get response (it will wait until time out). I am sure file upload is success and can upload up to 100MB file. (PHP max upload and post size is set to 100MB, max execution time is set to 300 seconds.)
Amazon Linux 2
Apache version: 2.4.54
PHP version: 7.2.34
CodeIgniter version: 3.1.11
Upload related code like this. After upload completed, it will bring file information to next page.
if($this->upload->do_upload('uploadfile')){
$file1 = $this->upload->data();
$arr_info['file']['file_size'] = $file1['file_size'];
$arr_info['file']['ori_file_name'] = $file1['orig_name'];
$arr_info['file']['file_extension'] = $file1['file_ext'];
$arr_info['file']['fullpath'] = $file1['full_path'];
}
else {
echo "Upload failed! Please try again!";
exit;
}
$pagedata['data'] = $arr_info;
$this->template->load('layout', '/build/end_upload', $pagedata);
When upload a 5.5MB filename schedule.json, it will success.
Select a 5.5 MB file to upload
It will go to next page and show file information (array) like this.
Browser can get response, file upload success.
But if I upload file larger than 10MB, although file can successfully upload to server, my browser will not get response and wait until timeout. Here is my /tmp folder where upload file placed. You can see a 61MB file name "2023TaipeiNewYear.mp4" successfully uploaded.
enter image description here
CodeIgniter logs are like this:
CI says it was finished
Since last few lines says it has loaded view file, and "Final output sent to browser". I think it means CodeIgniter had done his job. But browser still hang and wait until timeout.
I tested in Chrome(109.0.5414.119), FireFox (109.0.1), Edge(109.0.1518.78 ) but got the same result.
I wonder if php-fpm have some issue so open DEBUG mode to trace, when upload started it showed
[08-Feb-2023 05:37:39.040845] DEBUG: pid 8604, fpm_pctl_perform_idle_server_maintenance(), line 378: [pool www] currently 1 active children, 5 spare children, 6 running children. Spawning rate 1
and after few seconds, active children turn to 0, and file did uploaded to /tmp folder. But, browser still get nothing.
[08-Feb-2023 05:37:40.042082] DEBUG: pid 8604, fpm_pctl_perform_idle_server_maintenance(), line 378: [pool www] currently 0 active children, 6 spare children, 6 running children. Spawning rate 1
I think it means php-fpm had done his part.
some php.ini settings may be related:
max_input_time= 300
output_buffering= off
max_execution_time = 300
memory_limit = 512M
post_max_size = 100M
file_uploads = On
upload_max_filesize = 100M
I wonder if anything happened or hanged in upload process, or can load CodeIgniter view for some reason. so I try to write a log in server after upload, then echo result to browser.
if($this->upload->do_upload('uploadfile')){
$file1 = $this->upload->data();
$arr_info['success'] = 1;
$arr_info['file']['file_size'] = $file1['file_size'];
$arr_info['file']['file_name'] = $file_name;
$arr_info['file']['ori_file_name'] = $file1['orig_name'];
$arr_info['file']['file_md5'] = md5_file($file1['full_path']);
$arr_info['file']['file_extension'] = $file1['file_ext'];
$arr_info['file']['file_md5_type'] = 'md5';
}
else {
echo "Upload failed! Please try again!";
exit;
}
$log = json_encode($arr_info);
exec('echo "'. $log . '" >> /tmp/upload_log.txt &');
header('Content-Type: application/json; charset=utf-8');
echo $log;
flush();
exit;
After try to upload two files which are 8.2MB and 10.2MB, I get this log.
{success:1,file:{file_size:8217.24,file_name:s-test_upload.zip,ori_file_name:test_upload.zip,file_md5:34d8753e37df705fc3358c4b4e5e2754,file_extension:.zip,file_md5_type:md5}}
{success:1,file:{file_size:10250.2,file_name:s-AINTD.png,ori_file_name:AINTD.png,file_md5:0eb1b12a08ee913102cfb5db29a9589d,file_extension:.png,file_md5_type:md5}}
So two uploads are success, but only the first one can get JSON output on browser, the second one which larger than 10MB still hangs and get nothing response.
I can't see any error messages in php-fpm and apache logs.
Not sure what happens. If anyone needs any more information please let me know. Thanks!
try calling upload library with config:
$config['upload_path'] = './tmp/';
$config['allowed_types'] = 'json|mp4|jpg|png';
$config['max_size'] = 100000; //100MB
$config['max_width'] = 1024;
$config['max_height'] = 768;
$this->load->library('upload', $config);
https://codeigniter.com/userguide3/libraries/file_uploading.html#the-controller
put display_error in else block:
$this->upload->display_errors('<pre>', '</pre>');
if you have some time, please try it out to see what the result will be if you use move_upload_file() function https://www.php.net/manual/en/function.move-uploaded-file.php
check phpinfo() that the settings are real in php-side
((we also use codeigniter 3.1, we can easily upload a 500mb file))
After create a few other AWS instances to test, we finally find out that this is a HTTP protocol issue.
We were running services inside our internal network when coding on development environment, so we just use internal IP and HTTP for connection on dev servers.
After I register a real domain and give it SSL certification, running through HTTPS protocol to upload file more than 10MB would be okay.
But I don't think HTTP POST have any limitation before..... we had coding on HTTP only dev environment for years..... not sure if major browsers have a new limitations on HTTP protocol.

Symfony2's HttpFoundation/File/File.php cannot find temporary file when uploading a document (in MAMP)

I'm using MAMP on my local mac to test a Symfony2 application. I'm trying to upload a document, but keep running into a system 500 error : 'The file "/Applications/MAMP/tmp/php/[...]" does not exist.'
This is either an issue with my Symfony2 config or MAMP config - I'm not sure which.
The script itself succeeds in uploading a file:
$req = Request::createFromGlobals();
$uploadedFile = $req->files->get($file);
$file = time().'_'.str_replace(' ','_',$uploadedFile->getClientOriginalName());
if (!is_dir($this->uploads_dir))
{
mkdir($this->uploads_dir);
}
if ($uploadedFile->move($this->uploads_dir, $file))
{
$this->session->set('van.uploaded_file', $this->uploads_dir.$file);
}
else
{
$this->error[] = 'upload.failed';
}
$this->uploads_dir is simply '/uploads/' and indeed each time I run the script (despite the 500 errors) my files are loaded into the /uploads directory.
I'm not sure that it matters, but the script above is run from a service class (rather than from a controller.)
I have checked the /Applications/MAMP/tmp/php/ directory and there are no temporary upload files there. (But that may be because they have been moved to my /uploads folder!)
I've set the permissions for the /Applications/MAMP/tmp/php/ directory to 777 and still no luck.
I commented out the upload_tmp_dir in my php.ini file but that just triggers the same error for a different default directory on my computer:
; Temporary directory for HTTP uploaded files (will use system default if not
; specified).
; upload_tmp_dir = /Applications/MAMP/tmp/php
Here is the exact error from Symfony's error log:
CRITICAL - Uncaught PHP Exception Symfony\Component\HttpFoundation\File\Exception
\FileNotFoundException: "The file "/Applications/MAMP/tmp/php/phpYew2rT" does not exist" at
/Applications/MAMP/htdocs/tdp2013/Symfony/vendor/symfony/symfony/src/Symfony/Component
/HttpFoundation/File/File.php line 41
Any other ideas?
UPDATE:
I modified the script to upload the document using move_uploaded_file instead of Symfony's File component. I received the same error - meaning this is an issue with my MAMP configuration, not Symfony.
public function upload($file_name)
{
$this->session->remove('van.uploaded_file');
if (!is_dir($this->uploads_dir))
{
mkdir($this->uploads_dir);
}
$file = $this->uploads_dir.time().'_'.str_replace(' ','_',$_FILES[$file_name]["name"]);
move_uploaded_file($_FILES[$file_name]["tmp_name"], $file);
if (file_exists($file))
{
$this->session->set('van.uploaded_file', $file);
}
else
{
$this->error[] = 'upload.failed';
}
return $this;
}
Here are my php.ini settings:
;;;;;;;;;;;;;;;;
; File Uploads ;
;;;;;;;;;;;;;;;;
; Whether to allow HTTP file uploads.
file_uploads = On
; Temporary directory for HTTP uploaded files (will use system default if not
; specified).
upload_tmp_dir = /Applications/MAMP/tmp/php
; Maximum allowed size for uploaded files.
upload_max_filesize = 32M
What size is the file? I have had similar errors in the past and this was the cause.
I do not know about mamp but PHP, in general, has a 2MB file upload limit by default.
In order to increase it you will need to modify 2 settings in your php.ini
post_max_size = 16MB
upload_max_filesize = 16MB
Of course you can put any value in stead of 16.
If you are unable or unwilling to modify php.ini you may be able to change the values in php code as explained here

tempnam() not working on client server

I did a script, which has to load a file from a ftp-server then parses it. The code relies on tempname to store the temporarily store the ftp-file. On my developement server (with php 5.3.10), this works flawlessly, however on the client machine (with php 5.2.17) it does not and gives me:
Warning: ftp_rawlist() [function.ftp-rawlist]: Unable to create temporary file. Check permissions in temporary files directory.
Can someone give me a clue what i could do?
(I am a little weak on the possibiities of php)
I used this code:
define ("LOCALFILE",tempnam('/tmp', 'data-'));
define ("USER","myusername");
define ("PASS","mypassword");
define('SERVER', "ftpserver.com");
define ("DIR","/path/");
function getFTPFile(){
// connect
if(!($conn_id = #ftp_connect(SERVER))){
Error::throwOne("Could not connect to ".SERVER);
};
// login
if(!($login_result = #ftp_login($conn_id, USER, PASS))){
Error::throwOne("LOGIN INCORRECT! user:".USER." pass:".PASS);
};
// try to change the directory to somedir
if (!ftp_chdir($conn_id, DIR)) {
Error::throwOne("Couldn't change directory\n");
};
if(!($a = ftp_rawlist($conn_id, '-1t'))){
Error::throwOne("Couldn't get ftp_rawlist\n");
};
$server_file=($a[0]);
if (!ftp_get($conn_id, LOCALFILE, $server_file, FTP_BINARY)) {
Error::throwOne("Couldn't get file\n");
};
ftp_close($conn_id);
};
The error looks to me like system-generated and have nothing to do with your tmpname. Internally, FTP stores the file in its own temp file in temp filename in standard temp directory up to the point when it's downloaded - then moves it to the location you specified.
Try putting this code before your download code:
$tmpdir = sys_get_temp_dir();
echo "Temp dir: $tmpdir\n";
echo is_writable($tmpdir) ? "Temp dir is writable" : "Temp dir is not writable";
This will tell you if you have permissions to write to the system temp dir. I further suggest that you use this $tmpdir variable instead of hardcoding "/tmp" in your code.
I found the issue.
Since my hoster does not like the /tmp directory ( who would blame them )
i need to first set
putenv('TMPDIR=/the tmp-dir my provider gave me');
which then works with tempname
I found this occurred on Windows Server 2016 - and it was because my %TEMP% environment variable pointed to a subdirectory that didn't exist for whatever reason.
It did point to the correct one when I ran it as Administrator, though.

Uploading a image to a server + inserting filename to dB

The php:
//This is the directory where images will be saved
$target = "/images/";
$target = $target . basename( $_FILES['photo']['name']);
//This gets all the other information from the form
$strListItemPic=(mysql_real_escape_string($_FILES['photo']['name']));
//Writes the photo to the server
if(move_uploaded_file($_FILES['photo']['tmp_name'], $target))
{
//Tells you if its all ok
echo "The file ". basename( $_FILES['uploadedfile']['name']). "
has been uploaded, and your information has been added to the directory";
}
else {
//Gives and error if its not
echo "Sorry, there was a problem uploading your file.";
}
The html:
<input type="hidden" name="size" value="350000">
<input type="file" name="photo">
It's breaking out and giving "Sorry, there was a problem uploading your file.";
I'm inserting $strListItemPic later in a MySQL statement, so I can echo the picture in a variable elsewhere.
Any glaring errors in this code? Does my $target have to be absolute paths?
PHP errors:
Warning: move_uploaded_file(/xxxxxx/lists/images/test.gif):
failed to open stream: No such file or directory in
/home/virtual/site48/fst/var/www/html/xxxxxx/lists/itemedit.php on line 22
Warning: move_uploaded_file(): Unable to move '/tmp/phpJ3v7HV' to
'/xxxxxx/lists/images/test.gif'
in /home/virtual/site48/fst/var/www/html/xxxxxx/lists/itemedit.php on line 22
Fixed:
Added enctype="multipart/form-data" to <form>
Removed / before images in $target
Errors don't have to glare in the code.
Errors being raised at the time the code gets executed.
And these errors have to be noted and investigated.
at least add these 2 lines into your code and run it again.
ini_set('display_errors',1);
error_reporting(E_ALL);
or get the error message produced by move_uploaded_file any other way.
Trying to answer your question without an actual error message would be useless waste of time.
Your apache sub directory where you write (move)images must be writable i.e have permissions to write files. since it looks like you are on Linux cd to the directory and change permissions with:
cd /the/parent/directory/to/directory/where/files/are/supposed/to/be
chmod 777 theimagefilesdir/
Be sure to read permissions and choose one that fits you as 777 is very permissive and can be impractical to production but I use it in my local machine :)
Please check that you are using enctype in form tag

How to debug move_uploaded_file() in PHP

move_uploaded_file() won't work for me anymore, it was working fine and just stopped out of nowhere. Is there a way for me to check why it's not working anymore? Here's what I currently have, but it only returns TRUE or FALSE.
$status = move_uploaded_file($tempFile, $targetFile);
if($status) {
echo 'its good';
} else {
echo 'it failed';
}
I know the path is 100% correct and the directory is CHMOD 755. Is there anything I might be doing wrong?
Maybe this will work:
if(!move_uploaded_file($_FILES['attachement']['tmp_name'], $uploadfile)) {
echo 'Your file was not uploaded please try again
here are your debug informations:
'.print_r($_FILES);
} else {
echo 'image succesfully uploaded!';
}
Check your error reporting level (see error_reporting function). You should get a warning or notice that's a bit more descriptive.
Also, check that the user your PHP script runs as (usually the server's user, which is nobody or www-data on a lot of systems, but YMMV) owns the directory. With 755, only the owner of the directory can write to it.
Permissions of 755 means that only the owner of the directory can write to that directory.
So the question is, who is the owner and as what user is the web-server / php running?
If they don´t match, you can either change the ownership or the group (also changing the permissions to 775).

Categories