You’ll learn about the following:
- HTML Form Requirements for File Uploads
- PHP Configuration for File Uploads
- PHP $_FILES Array
PHP File Upload Error Codes - Moving Uploaded Files to a Safe Location
- Understanding File Upload Errors
Example: Simple File Uploading PHP Script
<?php //$file = isset($_FILES['upload']) ? $_FILES['upload'] : array(); $file = $_FILES['upload'] ?? []; if ( ! empty($file) && $file['error'] == 0 ) { echo 'name: ' . $file['name'] . '<br>'; echo 'type: ' . $file['type'] . '<br>'; echo 'size: ' . $file['size'] . '<br>'; echo 'error: ' . $file['error'] . '<br>'; echo 'tmp_name: ' . $file['tmp_name'] . '<br>'; echo 'full_path: ' . $file['full_path'] . '<br>'; } ?> <form action="example.php" method="post" enctype="multipart/form-data"> <input type="file" name="upload" > <input type="submit" name="submit" value="Upload"> </form>
HTML Form Requirements
The HTML form has to fulfill two requirements when uploading files to the web server:
- The
enctype
(encoding type) attribute has to be set to"multipart/form-data"
- The
method
attribute has to be set to"post"
Without these settings, the file upload does not work. Next, we need to add an input tag and set the value of its type attribute to file.
Adding a file upload field to a form:
<form action="example.php" method="post" enctype="multipart/form-data"> <input type="file" name="upload"> <input type="submit" name="submit" value="Upload"> </form>
Limiting Upload File Size in Form with MAX_FILE_SIZE
To restrict the upload file size add a hidden input field, set the name attribute value to MAX_FILE_SIZE and specify a maximum size (in bytes) for an upload file in value attribute:
<form action="example.php" method="post" enctype="multipart/form-data"> <input type="hidden" name="MAX_FILE_SIZE" value="15360"> <input type="file" name="upload"> <input type="submit" name="submit" value="Upload"> </form>
Note: The MAX_FILE_SIZE filed must place before the file input field, otherwise it won’t work.
PHP File Uploads Configuration
You can check whether your server supports file uploads by running phpinfo()
on your server. To do this, create a PHP file and add the following code:
<?php //info.php echo phpinfo();
Scroll down to the Core section, and find the file_uploads
directive, if the Local Value is On
, your server allowed the file uploads. If Off
, uploads have been disabled.
The following figure shows the important directives related to file uploads:
file_uploads
Whether or not to allow HTTP file uploads. If the Local Value isOn
, your server configuration allows file uploads.max_execution_time
:
The maximum time in seconds a script is allowed to run before it is terminated by the parser. For large files upload, the script may take a longer time (depending on the user’s internet speed). If the script takes longer, PHP generates a fatal error.max_file_uploads
:
The maximum number of files allowed to be uploaded simultaneously.max_input_time
:
The maximum time in seconds a script is allowed to parse input data (i.e. POST and GET). Uploading very large files may run out of time.post_max_size
:
The maximum allowed size (in bytes) of post data. To upload large files, this value must be larger thanupload_max_filesize
andmemory_limit
should be larger than this value.upload_max_filesize
:
The maximum size of an uploaded file. Thepost_max_size
must be larger than this value.upload_tmp_dir
:
A writable directory for temporarily storing uploaded files.
Understanding the $_FILES array
You can’t refer to an uploaded file in the $_POST
array in the same way you do with other form fields. PHP uses a separate superglobal array $_FILES
to retrieve the details of uploaded files. You can find the file upload form field under its name:
<?php if ($_SERVER['REQUEST_METHOD'] == 'POST') { echo '<pre>'; print_r($_FILES); echo '</pre>'; } ?> <form action="example.php" method="post" enctype="multipart/form-data"> <input type="file" name="upload"> <input type="submit" name="submit" value="Upload"> </form>
The following subkeys provide the information about the uploaded file:
$_FILES["upload"]["name"]
Original filename sent by the browser. Do not rely on the"name"
because this information can be forged. Also, some browsers do not always send the original filename, but the complete path to it. Therefore, always callbasename()
to extract the filename only:basename($_FILES['upload']['name'])
.$_FILES["upload"]["full_path"]
(PHP 8.1)
Contains the full path of the uploaded file. This is intended for use in conjunction withwebkitdirectory
(for the entire directory uploads).$_FILES["upload"]["type"]
The file’sMIME
type as sent by the client, not reliable$_FILES["upload"]["tmp_name"]
Temporary filename where PHP saved the uploaded file. PHP deletes the file when script execution is completed, so you need to save the file immediately by using themove_uploaded_file
function (discuss later).$_FILES["upload"]["size"]
Size of the file in bytes.$_FILES["upload"]["error"]
Status of upload, Error code 0 (or constantUPLOAD_ERR_OK
) means the upload was successful.
PHP File Upload Error Codes
- UPLOAD_ERR_OK
Value:0
, indicates successful upload - UPLOAD_ERR_INI_SIZE
Value:1
, file exceeds the maximum upload size specified in php.ini (default 2 MB). - UPLOAD_ERR_FORM_SIZE
Value:2
, file exceeds the size specified byMAX_FILE_SIZE
. - UPLOAD_ERR_PARTIAL
Value:3
, file only partially uploaded. - UPLOAD_ERR_NO_FILE
Value:4
, form submitted with no file specified. - UPLOAD_ERR_NO_TMP_DIR
Value:6
, no temporary folder defined. - UPLOAD_ERR_CANT_WRITE
Value:7
, cannot write the file to disk. - UPLOAD_ERR_EXTENSION
Value:8
, upload stopped by an unspecified PHP extension.
Example:
<?php if ( isset($_FILES['upload']) ) { switch ( $_FILES['upload']['error'] ) { case UPLOAD_ERR_OK: echo 'File successfully uploaded'; //code to move file break; case UPLOAD_ERR_INI_SIZE: echo 'File exceeds the maximum upload size specified in php.ini (default 2 MB)'; break; case UPLOAD_ERR_FORM_SIZE: echo 'File exceeds the size specified by MAX_FILE_SIZE'; break; case UPLOAD_ERR_PARTIAL: echo 'File only partially uploaded'; break; case UPLOAD_ERR_NO_FILE: echo 'Form submitted with no file specified'; break; case UPLOAD_ERR_NO_TMP_DIR: echo 'No temporary folder defined'; break; case UPLOAD_ERR_CANT_WRITE: echo 'Cannot write the file to disk'; break; case UPLOAD_ERR_EXTENSION: echo 'Upload stopped by an unspecified PHP extension'; } } ?> <form action="example.php" method="post" enctype="multipart/form-data"> <input type="hidden" name="MAX_FILE_SIZE" value="15360"> <input type="file" name="upload" > <input type="submit" name="submit" value="Upload"> </form>
Moving Uploaded Files to a Safe Location
<?php //Syntax move_uploaded_file(string $from, string $to): bool
When a user uploads a file PHP stores the file in a temporary location (set in the php.ini
directive upload_tmp_dir
) and deletes it upon completion of script execution. Therefore, you have to move (or save) the uploaded file within the script.
move_uploaded_file function
You must use the PHP function move_uploaded_file()
to move the uploaded file to another location. The move_uploaded_file()
function first does a sanity check, whether the filename you provide really is an uploaded file or if a malicious user just tried to trick you into moving /etc/passwd
or C:\boot.ini
somewhere else.
is_uploaded_file function
The is_uploaded_file function tests whether the file was uploaded via HTTP POST. It also test whether the filename you provide really is an uploaded file or if a malicious user just tried to trick you into moving /etc/passwd
or C:\boot.ini
somewhere else.
Moving an Uploaded File to a New Location
<?php if (isset($_FILES['upload']) && $_FILES['upload']['error'] == UPLOAD_ERR_OK && is_uploaded_file($_FILES['upload'][tmp_name']) ) { $from = $_FILES['upload']['tmp_name']; $to = 'uploads'.DIRECTORY_SEPARATOR .basename($_FILES['upload']['name']); if (move_uploaded_file($from, $to)) echo 'File moved'; else echo 'File not moved'; } ?> <form action="example.php" method="post" enctype="multipart/form-data"> <input type="file" name="upload" multiple> <input type="submit" name="submit" value="Upload"> </form>
Note: Different OSs use different directory separators, Windows uses \
and Linux uses /
. It is good practice to write DIRECTORY_SEPARATOR
constant instead of writing the /
or \
in your PHP scripts.
Common Errors
Why is permission denied?
Warning: move_uploaded_file(uploads/readme.txt): Failed to open stream: Permission denied in...
The directory (or folder) where you trying to move the uploaded file has no writeable permission. If your website is hosted on a Linux server you need to give global access (chmod
777) to the directory to which you want to upload files. You can use an FTP client to configure permissions of a directory if you intend to make files available publically to your website visitors.
Failed to open stream or Unable to move:
Warning: move_uploaded_file(uploads/readme.txt): Failed to open stream: No such file or directory in... Warning: move_uploaded_file(): Unable to move "D:\xampp\tmp\php5266.tmp" to "uploads/readme.txt" in ...
The above errors occurred when the directory where you are trying to move the file was not found. Check if you’ve written the correct path in the script.
Processing Forms in PHP: