You might think it is a hard work to upload a file. At the client side, do I need to write code to open the file, read its content, then post the content to server? At the server side, do I need to write code to get the file content, write it to a file on server?
Actually, things are not that complicated. The client work can be done by an html element <INPUT> in a form with the type “file”. The main work on server side is done by apache before running your php code. Specifically, apache will receive the uploaded file, save it to a temporary directory, and construct a global variable $_FILES to contain the information about the uploaded file. In your php code, you can simple copy the temporary file to any location you want.
W3schools gives an good example on how to upload a file with html and php.
<!DOCTYPE html> <html> <head> <title>upload file</title> </head> <body> <form action="upload.php" method="post" enctype="multipart/form-data"> Select image to upload: <input type="file" name="fileToUpload" id="fileToUpload"> <input type="submit" value="Upload Image" name="submit"> </form> </body> </html>
<?php $target_dir = "uploads/"; $target_file = $target_dir . basename($_FILES["fileToUpload"]["name"]); if (move_uploaded_file($_FILES["fileToUpload"]["tmp_name"], $target_file)) { echo "The file ". htmlspecialchars( basename( $_FILES["fileToUpload"]["name"])). " has been uploaded."; } else { echo "Sorry, there was an error uploading your file."; }
The <INPUT> of type “file” displays as a button with “Browse…” on it. Click the button, you can select a file on your local machine. Click the “Upload Image” button displayed by the <INPUT> element of type “submit”, the content of the file, together with the file name, are transferred to server. Note that the <INPUT> element has a name “fileToUpload”,which becomes a key in the server variable $_FILES. $_FILES[“fileToUpload”] has the following members:
- name: the file name on the client side
- tmp_name: the temporary file name on the server side, i.e., the name of the temporary file apache saves to
- error: a number if some error occurred
- size: the size of the file
move_uploaded_file will move the temporary file to a target location.
Things seem easy until you encounter an error. If you cannot upload a file, check the following settings.
First, you should check if the file_uploads and upload_tmp_dir are set in /etc/php.ini.
file_uploads = On upload_tmp_dir = /tmp
The php.ini comments the upload_tmp_dir line by default. Although it says “will use system default if not specified”, it actually does not use the default temporary directory /tmp as you can get by sys_get_temp_dir(). Without a temporary directory, Apache won’t save the file content it receives. $_FILES[“fileToUpload”][“error”] is set to 6, which means UPLOAD_ERR_NO_TMP_DIR. $_FILES[“fileToUpload”][“tmp_name”] is empty. The worst thing is in this case move_uploaded_file won’t generate any warning as claimed by its official document.
With upload_tmp_dir set, the second thing is to check if the temporary directory is readable and writable by apache. Without proper permission, the upload will fail. Of course, the target directory should be also writable by apache.
If you still fail to upload a file, the third thing is to check if the temporary directory is in the allowed paths for open_basedir. This apache instruction is typically specified in virtualhost settings in httpd.conf(php_admin_value open_basedir). If the temporary directory is not included in open_basedir, you will get errors like:
Warning: move_uploaded_file(): open_basedir restriction in effect. File(/tmp/phpxxxxxx) is not within the allowed path(s)…
Warning: move_uploaded_file(/tmp/phpmdxxxxx): failed to open stream: Operation not permitted in…
Warning: move_uploaded_file(): Unable to move ‘/tmp/phpmxxx’ to ….
A comprehensive checklist can be found here.