{"id":83,"date":"2021-03-08T00:15:22","date_gmt":"2021-03-08T00:15:22","guid":{"rendered":"https:\/\/phptutorial.net\/?page_id=83"},"modified":"2025-04-08T06:21:30","modified_gmt":"2025-04-08T06:21:30","slug":"php-file-upload","status":"publish","type":"page","link":"https:\/\/www.phptutorial.net\/php-tutorial\/php-file-upload\/","title":{"rendered":"PHP File Upload"},"content":{"rendered":"\n<p><strong>Summary<\/strong>: in this tutorial, you will learn how to create a file upload form and process uploaded files securely in PHP.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id='introduction-to-the-file-input-element'>Introduction to the file input element <a href=\"#introduction-to-the-file-input-element\" class=\"anchor\" id=\"introduction-to-the-file-input-element\" title=\"Anchor for Introduction to the file input element\">#<\/a><\/h2>\n\n\n\n<p>The <code>&lt;input&gt;<\/code> element with the <code>type=\"file\"<\/code> allows users to select one or more files from their storage and upload them to the server via the <a href=\"https:\/\/phptutorial.net\/php-tutorial\/php-form\/\">form submission<\/a>.<\/p>\n\n\n\n<p>The following shows the file input element:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-1\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\">&lt;input type=<span class=\"hljs-string\">\"file\"<\/span> id=<span class=\"hljs-string\">\"file\"<\/span> name=<span class=\"hljs-string\">\"file\"<\/span>&gt;<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-1\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>The <code>value<\/code> of the <code>&lt;input&gt;<\/code> element will hold the path to the selected file. To <a href=\"https:\/\/phptutorial.net\/php-tutorial\/php-upload-multiple-files\/\">upload multiple files<\/a>, you add the <code>multiple<\/code> attribute to the <code>&lt;input&gt;<\/code> element like this:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-2\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\">&lt;input type=<span class=\"hljs-string\">\"file\"<\/span> id=<span class=\"hljs-string\">\"file\"<\/span> name=<span class=\"hljs-string\">\"file\"<\/span> multiple&gt;<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-2\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>In this case, the <code>value<\/code> attribute will hold the path of the first file in the selected file list. Note that you&#8217;ll learn how to <a href=\"https:\/\/phptutorial.net\/php-tutorial\/php-upload-multiple-files\/\">upload multiple files<\/a> in the next tutorial.<\/p>\n\n\n\n<p>To allow users to upload files with specific types, you can use the <code>accept<\/code> attribute. The value of the <code>accept<\/code> attribute is a unique file type specifier, which can be:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>A valid case-insensitive file name extension e.g., <code>.jpg<\/code>, <code>.pdf<\/code>, <code>.txt<\/code><\/li>\n\n\n\n<li>A valid MIME type string<\/li>\n\n\n\n<li>A string like <code>image\/*<\/code> (any image file), <code>video\/*<\/code> (any video file), <code>audio\/*<\/code> (any audio file).<\/li>\n<\/ul>\n\n\n\n<p>If you allow user to upload multiple file types, you need to separate them using a comma (<code>,<\/code>). For example, the following setting allows users to upload <code>.png<\/code> and <code>.jpeg<\/code> images:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-3\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\">&lt;input type=<span class=\"hljs-string\">\"file\"<\/span> accept=<span class=\"hljs-string\">\"image\/png, image\/jpeg\"<\/span> name=<span class=\"hljs-string\">\"file\"<\/span>&gt;<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-3\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>The <code>&lt;form&gt;<\/code> element that contains the file input element must have the <code>enctype<\/code> attribute with the value  <code>multipart\/form-data<\/code>:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-4\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\">&lt;form enctype=<span class=\"hljs-string\">\"multipart\/form-data\"<\/span> action=<span class=\"hljs-string\">\"upload.php\"<\/span> method=<span class=\"hljs-string\">\"post\"<\/span>&gt;\n&lt;\/form&gt;<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-4\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>If you don&#8217;t use the <code>enctype<\/code> attribute, you will not be able to upload files.<\/p>\n\n\n\n<p>The following illustrates a simple form for uploading a single file to the web server:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-5\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\">&lt;!DOCTYPE html&gt;\n&lt;html lang=<span class=\"hljs-string\">\"en\"<\/span>&gt;\n&lt;head&gt;\n    &lt;meta charset=<span class=\"hljs-string\">\"UTF-8\"<\/span>\/&gt;\n    &lt;meta name=<span class=\"hljs-string\">\"viewport\"<\/span> content=<span class=\"hljs-string\">\"width=device-width, initial-scale=1.0\"<\/span>\/&gt;\n    &lt;title&gt;PHP File Upload&lt;\/title&gt;\n&lt;\/head&gt;\n&lt;body&gt;\n&lt;form enctype=<span class=\"hljs-string\">\"multipart\/form-data\"<\/span> action=<span class=\"hljs-string\">\"upload.php\"<\/span> method=<span class=\"hljs-string\">\"post\"<\/span>&gt;\n    &lt;div&gt;\n        &lt;label <span class=\"hljs-keyword\">for<\/span>=<span class=\"hljs-string\">\"file\"<\/span>&gt;Select a file:&lt;\/label&gt;\n        &lt;input type=<span class=\"hljs-string\">\"file\"<\/span> id=<span class=\"hljs-string\">\"file\"<\/span> name=<span class=\"hljs-string\">\"file\"<\/span>\/&gt;\n    &lt;\/div&gt;\n    &lt;div&gt;\n       &lt;button type=<span class=\"hljs-string\">\"submit\"<\/span>&gt;Upload&lt;\/button&gt;\n    &lt;\/div&gt;\n&lt;\/form&gt;\n&lt;\/body&gt;\n&lt;\/html&gt;<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-5\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h2 class=\"wp-block-heading\" id='php-file-upload-configuration'>PHP file upload configuration <a href=\"#php-file-upload-configuration\" class=\"anchor\" id=\"php-file-upload-configuration\" title=\"Anchor for PHP file upload configuration\">#<\/a><\/h2>\n\n\n\n<p>PHP has some important options that control the file upload. These options are in the <code>php.ini<\/code> file. <\/p>\n\n\n\n<p>If you don&#8217;t know where to find your <code>php.ini<\/code> file, you can use the <code>php_ini_loaded_file()<\/code> function as follows:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-6\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\"><span class=\"hljs-meta\">&lt;?php<\/span>\n\n\n<span class=\"hljs-keyword\">echo<\/span> php_ini_loaded_file();<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-6\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>It&#8217;ll return the following file path if you use XAMPP on Windows:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-7\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\">C:\\xampp\\php\\php.ini<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-7\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Here are the important settings for file uploads in the <code>php.ini<\/code> file:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-8\" data-shcb-language-name=\"plaintext\" data-shcb-language-slug=\"plaintext\"><span><code class=\"hljs language-plaintext\">; Whether to allow HTTP file uploads.\nfile_uploads=On\n\n; Temporary directory for HTTP uploaded files (will use system default if not\n; specified).\nupload_tmp_dir=\"C:\\xampp\\tmp\"\n\n; Maximum allowed size for uploaded files.\nupload_max_filesize=2M\n\n; Maximum number of files that can be uploaded via a single request\nmax_file_uploads=20<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-8\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">plaintext<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">plaintext<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h3 class=\"wp-block-heading\" id='file_uploads'>file_uploads <a href=\"#file_uploads\" class=\"anchor\" id=\"file_uploads\" title=\"Anchor for file_uploads\">#<\/a><\/h3>\n\n\n\n<p>The <code>file_upload<\/code> directive should be <code>On<\/code> to allow file upload. It defaults to <code>On<\/code>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id='upload_max_filesize'>upload_max_filesize <a href=\"#upload_max_filesize\" class=\"anchor\" id=\"upload_max_filesize\" title=\"Anchor for upload_max_filesize\">#<\/a><\/h3>\n\n\n\n<p>The <code>upload_max_filesize<\/code> specifies the maximum size of the uploaded file. By default, it&#8217;s 2M (MB). If you get an error saying that the file exceeds <code>upload_max_filesize<\/code>, you need to increase this value.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id='upload_tmp_dir'>upload_tmp_dir <a href=\"#upload_tmp_dir\" class=\"anchor\" id=\"upload_tmp_dir\" title=\"Anchor for upload_tmp_dir\">#<\/a><\/h3>\n\n\n\n<p>The <code>upload_tmp_dir<\/code> specifies the directory that stores the uploaded files temporarily.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id='post_max_size'>post_max_size <a href=\"#post_max_size\" class=\"anchor\" id=\"post_max_size\" title=\"Anchor for post_max_size\">#<\/a><\/h3>\n\n\n\n<p>The <code>post_max_size<\/code> specifies the maximum size of the <code>POST<\/code> data. Since you&#8217;ll upload files with the <code>POST<\/code> request, you need to make sure that the <code>post_max_size<\/code> is greater than <code>upload_max_size<\/code>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id='max_file_uploads'>max_file_uploads <a href=\"#max_file_uploads\" class=\"anchor\" id=\"max_file_uploads\" title=\"Anchor for max_file_uploads\">#<\/a><\/h3>\n\n\n\n<p>The <code>max_file_uploads<\/code> directive limits the number of files you can upload at a time.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id='handling-file-uploads-in-php'>Handling File uploads in PHP <a href=\"#handling-file-uploads-in-php\" class=\"anchor\" id=\"handling-file-uploads-in-php\" title=\"Anchor for Handling File uploads in PHP\">#<\/a><\/h2>\n\n\n\n<p>To access the information of an uploaded file, you use the <code>$_FILES<\/code> array. <\/p>\n\n\n\n<p>For example, if the name of the file input element is <code>file<\/code>, you can access the uploaded file via <code>$_FILES['file']<\/code>.<\/p>\n\n\n\n<p>The <code>$_FILE['file']<\/code> is an <a href=\"https:\/\/phptutorial.net\/php-tutorial\/php-associative-arrays\/\">associative array<\/a> that consists of the following keys:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>name<\/code>: The name of the uploaded file.<\/li>\n\n\n\n<li><code>type<\/code>: The MIME type of the upload file e.g., <code>image\/jpeg<\/code> for JPEG image or <code>application\/pdf<\/code> for PDF file.<\/li>\n\n\n\n<li><code>size<\/code> The size of the uploaded file in bytes.<\/li>\n\n\n\n<li><code>tmp_name<\/code>: The temporary file on the server that stored the uploaded filename. If the uploaded file is too large, the <code>tmp_name<\/code> is <code>\"none\"<\/code>.<\/li>\n\n\n\n<li><code>error<\/code>:  The error code that describes the upload status e.g., <code>UPLOAD_ERR_OK<\/code> means the file was uploaded successfully. <a href=\"https:\/\/www.php.net\/manual\/en\/filesystem.constants.php#constant.upload-err-cant-write\" target=\"_blank\" rel=\"noreferrer noopener\">More error messages here<\/a>.<\/li>\n<\/ul>\n\n\n\n<p>The following defines <code>MESSAGES<\/code> array that maps error codes with the messages:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-9\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\"><span class=\"hljs-keyword\">const<\/span> MESSAGES = &#91;\n    UPLOAD_ERR_OK =&gt; <span class=\"hljs-string\">'File uploaded successfully'<\/span>,\n    UPLOAD_ERR_INI_SIZE =&gt; <span class=\"hljs-string\">'File is too big to upload'<\/span>,\n    UPLOAD_ERR_FORM_SIZE =&gt; <span class=\"hljs-string\">'File is too big to upload'<\/span>,\n    UPLOAD_ERR_PARTIAL =&gt; <span class=\"hljs-string\">'File was only partially uploaded'<\/span>,\n    UPLOAD_ERR_NO_FILE =&gt; <span class=\"hljs-string\">'No file was uploaded'<\/span>,\n    UPLOAD_ERR_NO_TMP_DIR =&gt; <span class=\"hljs-string\">'Missing a temporary folder on the server'<\/span>,\n    UPLOAD_ERR_CANT_WRITE =&gt; <span class=\"hljs-string\">'File is failed to save to disk.'<\/span>,\n    UPLOAD_ERR_EXTENSION =&gt; <span class=\"hljs-string\">'File is not allowed to upload to this server'<\/span>,\n];<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-9\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>If you want to get a message based on an error code, you can look it up in the <code>MESSAGES<\/code> array like this:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-10\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\">$message = MESSAGES&#91;$_FILES&#91;<span class=\"hljs-string\">'file'<\/span>]&#91;<span class=\"hljs-string\">'error'<\/span>]];<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-10\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>When a file is uploaded successfully, it is stored in a temporary directory on the server. And you can use the <code>move_uploaded_file()<\/code> function to move the file from the temporary directory to another one. <\/p>\n\n\n\n<p>The <code>move_uploaded_file()<\/code> function accepts two arguments:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>filename<\/code>: is the file name of the uploaded file which is <code>$_FILES['file']['tmp_name']<\/code>.<\/li>\n\n\n\n<li><code>destination<\/code>: is the destination of the moved file.<\/li>\n<\/ul>\n\n\n\n<p>The <code>move_uploaded_file()<\/code> function returns <code>true<\/code> if it moves the file successfully; otherwise, it returns <code>false<\/code>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id='security-measures'>Security measures <a href=\"#security-measures\" class=\"anchor\" id=\"security-measures\" title=\"Anchor for Security measures\">#<\/a><\/h2>\n\n\n\n<p>All the information in the <code>$_FILES<\/code> variable cannot be trusted except for the <code>tmp_name<\/code>. Hackers can manipulate the <code>$_FILES<\/code> and uploads the malicious script to the server.<\/p>\n\n\n\n<p>To prevent this, you need to validate the information in the <code>$_FILES<\/code>.<\/p>\n\n\n\n<p>First, check if the file input name is in the <code>$_FILES<\/code> variable by using the <code><a href=\"https:\/\/phptutorial.net\/php-tutorial\/php-isset\/\">isset()<\/a><\/code>:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-11\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\"><span class=\"hljs-keyword\">if<\/span>(! <span class=\"hljs-keyword\">isset<\/span>($_FILES&#91;<span class=\"hljs-string\">'file'<\/span>]) ) {\n   <span class=\"hljs-comment\">\/\/ error<\/span>\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-11\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>In this example, the <code>'file'<\/code> is the name of the file input element.<\/p>\n\n\n\n<p>Second, check the actual size of the file by calling the <code>filesize()<\/code> function and compare its result with the maximum allowed file size. You should not trust the <code>size<\/code> provided by the <code>$_FILES<\/code>. For example:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-12\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\"><span class=\"hljs-keyword\">const<\/span> MAX_SIZE  = <span class=\"hljs-number\">5<\/span> * <span class=\"hljs-number\">1024<\/span> * <span class=\"hljs-number\">1024<\/span>; <span class=\"hljs-comment\">\/\/  5MB<\/span>\n\n<span class=\"hljs-keyword\">if<\/span> (filesize($_FILES&#91;<span class=\"hljs-string\">'file'<\/span>]&#91;<span class=\"hljs-string\">'tmp_name'<\/span>]) &gt; MAX_SIZE) {\n   <span class=\"hljs-comment\">\/\/ error<\/span>\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-12\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p class=\"note\">Note that the <code>MAX_SIZE<\/code> must not be greater than <code>upload_max_filesize<\/code> specified in the <code>php.ini<\/code>.<\/p>\n\n\n\n<p>The size of a file is in bytes, which is not human-readable. To make it more readable, we can define a function that converts the bytes to a human-readable format e.g., 1.20M, 2.51G:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-13\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\"><span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">format_filesize<\/span><span class=\"hljs-params\">(int $bytes, int $decimals = <span class=\"hljs-number\">2<\/span>)<\/span>: <span class=\"hljs-title\">string<\/span>\n<\/span>{\n    $units = <span class=\"hljs-string\">'BKMGTP'<\/span>;\n    $factor = floor((strlen($bytes) - <span class=\"hljs-number\">1<\/span>) \/ <span class=\"hljs-number\">3<\/span>);\n\n    <span class=\"hljs-keyword\">return<\/span> sprintf(<span class=\"hljs-string\">\"%.{$decimals}f\"<\/span>, $bytes \/ pow(<span class=\"hljs-number\">1024<\/span>, $factor)) . $units&#91;(int)$factor];\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-13\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Third, validate the MIME type of the file against the allowed file types. To do this, you need to define a list of allowed files:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-14\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\"><span class=\"hljs-keyword\">const<\/span> ALLOWED_FILES = &#91;\n   <span class=\"hljs-string\">'image\/png'<\/span> =&gt; <span class=\"hljs-string\">'png'<\/span>,\n   <span class=\"hljs-string\">'image\/jpeg'<\/span> =&gt; <span class=\"hljs-string\">'jpg'<\/span>\n];<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-14\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>To get the real mime type of a file, you use three functions: <code>finfo_open()<\/code>, <code>finfo_file()<\/code>, and <code>finfo_close()<\/code>. <\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>The <code>finfo_open()<\/code> returns a new <code>fileinfo<\/code> resource.<\/li>\n\n\n\n<li>The <code>finfo_file()<\/code> returns the information about the file.<\/li>\n\n\n\n<li>The <code>finfo_close()<\/code> closes the <code>fileinfo<\/code> resource.<\/li>\n<\/ul>\n\n\n\n<p>To make it easy and reusable, you can define a function <code>get_mime_type()<\/code> like this:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-15\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\"><span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">get_mime_type<\/span><span class=\"hljs-params\">(string $filename)<\/span>\n<\/span>{\n    $info = finfo_open(FILEINFO_MIME_TYPE);\n    <span class=\"hljs-keyword\">if<\/span> (!$info) {\n        <span class=\"hljs-keyword\">return<\/span> <span class=\"hljs-keyword\">false<\/span>;\n    }\n\n    $mime_type = finfo_file($info, $filename);\n    finfo_close($info);\n\n    <span class=\"hljs-keyword\">return<\/span> $mime_type;\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-15\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>The <code>get_mime_type()<\/code> function accepts a filename and returns the MIME type of the file. It&#8217;ll return <code>false<\/code> if an error occurs.<\/p>\n\n\n\n<p class=\"note\">Note that the Internet Assigned Numbers Authority (IANA) is in charge of all official MIME types, and you can find the complete list on their <a href=\"https:\/\/www.iana.org\/assignments\/media-types\/media-types.xhtml\" target=\"_blank\" rel=\"noreferrer noopener nofollow\">MIME type page<\/a>.<\/p>\n\n\n\n<p>If an error occurs or validation fails, you can set a flash message and redirect the browser back to the upload page. The following function sets a flash message and performs a redirection:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-16\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\"><span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">redirect_with_message<\/span><span class=\"hljs-params\">(string $message, string $type=FLASH_ERROR, string $name=<span class=\"hljs-string\">'upload'<\/span>, string $location=<span class=\"hljs-string\">'index.php'<\/span>)<\/span>: <span class=\"hljs-title\">void<\/span>\n<\/span>{\n    flash($name, $message, $type);\n    header(<span class=\"hljs-string\">\"Location: $location\"<\/span>, <span class=\"hljs-keyword\">true<\/span>, <span class=\"hljs-number\">303<\/span>);\n    <span class=\"hljs-keyword\">exit<\/span>;\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-16\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Note that we use the <code>flash()<\/code> function defined in the <code>flash.php<\/code> file. The <code>flash()<\/code> function shows a session-based flash message. <a href=\"https:\/\/phptutorial.net\/php-tutorial\/php-flash-messages\/\">Check out the flash message tutorial here<\/a>.<\/p>\n\n\n\n<p>The following shows how to use the <code>redirection_with_message()<\/code> function:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-17\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\"><span class=\"hljs-keyword\">if<\/span>(error) {\n   redirect_with_message(<span class=\"hljs-string\">'An error occurred'<\/span>);\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-17\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>The <code>return<\/code> statement ends the current script.<\/p>\n\n\n\n<p>Since all of these functions <code>get_mime_type()<\/code>, <code>format_filesize()<\/code>, and <code>redirect_with_message()<\/code> are reusable, you can add them to the <code>functions.php<\/code> file like this:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-18\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\"><span class=\"hljs-meta\">&lt;?php<\/span>\n\n<span class=\"hljs-comment\">\/**\n *  Messages associated with the upload error code\n *\/<\/span>\n<span class=\"hljs-keyword\">const<\/span> MESSAGES = &#91;\n    UPLOAD_ERR_OK =&gt; <span class=\"hljs-string\">'File uploaded successfully'<\/span>,\n    UPLOAD_ERR_INI_SIZE =&gt; <span class=\"hljs-string\">'File is too big to upload'<\/span>,\n    UPLOAD_ERR_FORM_SIZE =&gt; <span class=\"hljs-string\">'File is too big to upload'<\/span>,\n    UPLOAD_ERR_PARTIAL =&gt; <span class=\"hljs-string\">'File was only partially uploaded'<\/span>,\n    UPLOAD_ERR_NO_FILE =&gt; <span class=\"hljs-string\">'No file was uploaded'<\/span>,\n    UPLOAD_ERR_NO_TMP_DIR =&gt; <span class=\"hljs-string\">'Missing a temporary folder on the server'<\/span>,\n    UPLOAD_ERR_CANT_WRITE =&gt; <span class=\"hljs-string\">'File is failed to save to disk.'<\/span>,\n    UPLOAD_ERR_EXTENSION =&gt; <span class=\"hljs-string\">'File is not allowed to upload to this server'<\/span>,\n];\n\n<span class=\"hljs-comment\">\/**\n * Return a mime type of file or false if an error occurred\n *\n * <span class=\"hljs-doctag\">@param<\/span> string $filename\n * <span class=\"hljs-doctag\">@return<\/span> string | bool\n *\/<\/span>\n<span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">get_mime_type<\/span><span class=\"hljs-params\">(string $filename)<\/span>\n<\/span>{\n    $info = finfo_open(FILEINFO_MIME_TYPE);\n    <span class=\"hljs-keyword\">if<\/span> (!$info) {\n        <span class=\"hljs-keyword\">return<\/span> <span class=\"hljs-keyword\">false<\/span>;\n    }\n\n    $mime_type = finfo_file($info, $filename);\n    finfo_close($info);\n\n    <span class=\"hljs-keyword\">return<\/span> $mime_type;\n}\n\n<span class=\"hljs-comment\">\/**\n * Return a human-readable file size\n *\n * <span class=\"hljs-doctag\">@param<\/span> int $bytes\n * <span class=\"hljs-doctag\">@param<\/span> int $decimals\n * <span class=\"hljs-doctag\">@return<\/span> string\n *\/<\/span>\n<span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">format_filesize<\/span><span class=\"hljs-params\">(int $bytes, int $decimals = <span class=\"hljs-number\">2<\/span>)<\/span>: <span class=\"hljs-title\">string<\/span>\n<\/span>{\n    $units = <span class=\"hljs-string\">'BKMGTP'<\/span>;\n    $factor = floor((strlen($bytes) - <span class=\"hljs-number\">1<\/span>) \/ <span class=\"hljs-number\">3<\/span>);\n\n    <span class=\"hljs-keyword\">return<\/span> sprintf(<span class=\"hljs-string\">\"%.{$decimals}f\"<\/span>, $bytes \/ pow(<span class=\"hljs-number\">1024<\/span>, $factor)) . $units&#91;(int)$factor];\n}\n\n\n<span class=\"hljs-comment\">\/**\n * Redirect user with a session based flash message\n * <span class=\"hljs-doctag\">@param<\/span> string $message\n * <span class=\"hljs-doctag\">@param<\/span> string $type\n * <span class=\"hljs-doctag\">@param<\/span> string $name\n * <span class=\"hljs-doctag\">@param<\/span> string $location\n * <span class=\"hljs-doctag\">@return<\/span> void\n *\/<\/span>\n<span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">redirect_with_message<\/span><span class=\"hljs-params\">(string $message, string $type=FLASH_ERROR, string $name=<span class=\"hljs-string\">'upload'<\/span>, string $location=<span class=\"hljs-string\">'index.php'<\/span>)<\/span>: <span class=\"hljs-title\">void<\/span>\n<\/span>{\n    flash($name, $message, $type);\n    header(<span class=\"hljs-string\">\"Location: $location\"<\/span>, <span class=\"hljs-keyword\">true<\/span>, <span class=\"hljs-number\">303<\/span>);\n    <span class=\"hljs-keyword\">exit<\/span>;\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-18\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h2 class=\"wp-block-heading\" id='using-max_file_size-form-field'>Using MAX_FILE_SIZE form field <a href=\"#using-max_file_size-form-field\" class=\"anchor\" id=\"using-max_file_size-form-field\" title=\"Anchor for Using MAX_FILE_SIZE form field\">#<\/a><\/h2>\n\n\n\n<p>If you place a field with the name <code>MAX_FILE_SIZE<\/code> before a file input element in the form, PHP will use that value instead of <code>upload_max_filesize<\/code> for validating the file size.<\/p>\n\n\n\n<p>For example:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-19\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">form<\/span> <span class=\"hljs-attr\">enctype<\/span>=<span class=\"hljs-string\">\"multipart\/form-data\"<\/span> <span class=\"hljs-attr\">action<\/span>=<span class=\"hljs-string\">\"upload.php\"<\/span> <span class=\"hljs-attr\">method<\/span>=<span class=\"hljs-string\">\"post\"<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">label<\/span> <span class=\"hljs-attr\">for<\/span>=<span class=\"hljs-string\">\"file\"<\/span>&gt;<\/span>Select a file:<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">label<\/span>&gt;<\/span>\n        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">input<\/span> <span class=\"hljs-attr\">type<\/span>=<span class=\"hljs-string\">\"hidden\"<\/span> <span class=\"hljs-attr\">name<\/span>=<span class=\"hljs-string\">\"MAX_FILE_SIZE\"<\/span> <span class=\"hljs-attr\">value<\/span>=<span class=\"hljs-string\">\"10240\"<\/span>\/&gt;<\/span>\n        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">input<\/span> <span class=\"hljs-attr\">type<\/span>=<span class=\"hljs-string\">\"file\"<\/span> <span class=\"hljs-attr\">id<\/span>=<span class=\"hljs-string\">\"file\"<\/span> <span class=\"hljs-attr\">name<\/span>=<span class=\"hljs-string\">\"file\"<\/span>\/&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">button<\/span> <span class=\"hljs-attr\">type<\/span>=<span class=\"hljs-string\">\"submit\"<\/span>&gt;<\/span>Upload<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">button<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">form<\/span>&gt;<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-19\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">HTML, XML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">xml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>In this example, the <code>MAX_FILE_SIZE<\/code> is <code>10KB<\/code>. If you upload a file that is larger than <code>10KB<\/code> PHP will issue an error. However, it&#8217;s easy to manipulate this field so you should never rely on it for security purposes.<\/p>\n\n\n\n<p class=\"note\">Note that you cannot set the <code>MAX_FILE_SIZE<\/code> larger than the <code>upload_max_filesize<\/code> directive in the <code>php.ini<\/code> file.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id='php-file-upload-example'>PHP file upload example <a href=\"#php-file-upload-example\" class=\"anchor\" id=\"php-file-upload-example\" title=\"Anchor for PHP file upload example\">#<\/a><\/h2>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"471\" height=\"306\" src=\"https:\/\/phptutorial.net\/wp-content\/uploads\/2025\/04\/php-file-upload.png\" alt=\"php file upload\" class=\"wp-image-3304\" srcset=\"https:\/\/www.phptutorial.net\/wp-content\/uploads\/2025\/04\/php-file-upload.png 471w, https:\/\/www.phptutorial.net\/wp-content\/uploads\/2025\/04\/php-file-upload-300x195.png 300w\" sizes=\"auto, (max-width: 471px) 100vw, 471px\" \/><\/figure>\n\n\n\n<p>First, create the following directory structure:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-20\" data-shcb-language-name=\"plaintext\" data-shcb-language-slug=\"plaintext\"><span><code class=\"hljs language-plaintext\">\u251c\u2500\u2500 inc\n|  \u251c\u2500\u2500 flash.php\n|  \u2514\u2500\u2500 functions.php\n\u251c\u2500\u2500 index.php\n\u251c\u2500\u2500 upload.php\n\u2514\u2500\u2500 uploads<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-20\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">plaintext<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">plaintext<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Second, add the following file upload form to the <code>index.php<\/code> file:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-21\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\"><span class=\"hljs-meta\">&lt;?php<\/span>\nsession_start();\n<span class=\"hljs-keyword\">require_once<\/span> <span class=\"hljs-keyword\">__DIR__<\/span> . <span class=\"hljs-string\">'\/inc\/flash.php'<\/span>;\n<span class=\"hljs-meta\">?&gt;<\/span>\n&lt;!DOCTYPE html&gt;\n&lt;html lang=<span class=\"hljs-string\">\"en\"<\/span>&gt;\n&lt;head&gt;\n    &lt;meta charset=<span class=\"hljs-string\">\"UTF-8\"<\/span>\/&gt;\n    &lt;meta name=<span class=\"hljs-string\">\"viewport\"<\/span> content=<span class=\"hljs-string\">\"width=device-width, initial-scale=1.0\"<\/span>\/&gt;\n    &lt;link rel=<span class=\"hljs-string\">\"stylesheet\"<\/span> href=<span class=\"hljs-string\">\"https:\/\/phptutorial.net\/app\/css\/style.css\"<\/span>\/&gt;\n    &lt;title&gt;PHP File Upload&lt;\/title&gt;\n&lt;\/head&gt;\n&lt;body&gt;\n\n<span class=\"hljs-meta\">&lt;?php<\/span> flash(<span class=\"hljs-string\">'upload'<\/span>) <span class=\"hljs-meta\">?&gt;<\/span>\n\n&lt;main&gt;\n    &lt;form enctype=<span class=\"hljs-string\">\"multipart\/form-data\"<\/span> action=<span class=\"hljs-string\">\"upload.php\"<\/span> method=<span class=\"hljs-string\">\"post\"<\/span>&gt;\n        &lt;div&gt;\n            &lt;label <span class=\"hljs-keyword\">for<\/span>=<span class=\"hljs-string\">\"file\"<\/span>&gt;Select a file:&lt;\/label&gt;\n            &lt;input type=<span class=\"hljs-string\">\"file\"<\/span> id=<span class=\"hljs-string\">\"file\"<\/span> name=<span class=\"hljs-string\">\"file\"<\/span>\/&gt;\n        &lt;\/div&gt;\n        &lt;div&gt;\n            &lt;button type=<span class=\"hljs-string\">\"submit\"<\/span>&gt;Upload&lt;\/button&gt;\n        &lt;\/div&gt;\n    &lt;\/form&gt;\n&lt;\/main&gt;\n&lt;\/body&gt;\n&lt;\/html&gt;<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-21\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>The <code>index.php<\/code> file also contains a form for uploading a file. The <code>upload.php<\/code> file will handle the upload.<\/p>\n\n\n\n<p>Third, add the following code to the <code>upload.php<\/code> file to process the uploaded file:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-22\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\"><span class=\"hljs-meta\">&lt;?php<\/span>\n\nsession_start();\n\n<span class=\"hljs-keyword\">require_once<\/span> <span class=\"hljs-keyword\">__DIR__<\/span> . <span class=\"hljs-string\">'\/inc\/flash.php'<\/span>;\n<span class=\"hljs-keyword\">require_once<\/span> <span class=\"hljs-keyword\">__DIR__<\/span> . <span class=\"hljs-string\">'\/inc\/functions.php'<\/span>;\n\n<span class=\"hljs-keyword\">const<\/span> ALLOWED_FILES = &#91;\n    <span class=\"hljs-string\">'image\/png'<\/span> =&gt; <span class=\"hljs-string\">'png'<\/span>,\n    <span class=\"hljs-string\">'image\/jpeg'<\/span> =&gt; <span class=\"hljs-string\">'jpg'<\/span>\n];\n\n<span class=\"hljs-keyword\">const<\/span> MAX_SIZE = <span class=\"hljs-number\">5<\/span> * <span class=\"hljs-number\">1024<\/span> * <span class=\"hljs-number\">1024<\/span>; <span class=\"hljs-comment\">\/\/  5MB<\/span>\n\n<span class=\"hljs-keyword\">const<\/span> UPLOAD_DIR = <span class=\"hljs-keyword\">__DIR__<\/span> . <span class=\"hljs-string\">'\/uploads'<\/span>;\n\n\n$is_post_request = strtolower($_SERVER&#91;<span class=\"hljs-string\">'REQUEST_METHOD'<\/span>]) === <span class=\"hljs-string\">'post'<\/span>;\n$has_file = <span class=\"hljs-keyword\">isset<\/span>($_FILES&#91;<span class=\"hljs-string\">'file'<\/span>]);\n\n<span class=\"hljs-keyword\">if<\/span> (!$is_post_request || !$has_file) {\n    redirect_with_message(<span class=\"hljs-string\">'Invalid file upload operation'<\/span>, FLASH_ERROR);\n}\n\n<span class=\"hljs-comment\">\/\/<\/span>\n$status = $_FILES&#91;<span class=\"hljs-string\">'file'<\/span>]&#91;<span class=\"hljs-string\">'error'<\/span>];\n$filename = $_FILES&#91;<span class=\"hljs-string\">'file'<\/span>]&#91;<span class=\"hljs-string\">'name'<\/span>];\n$tmp = $_FILES&#91;<span class=\"hljs-string\">'file'<\/span>]&#91;<span class=\"hljs-string\">'tmp_name'<\/span>];\n\n\n<span class=\"hljs-comment\">\/\/ an error occurs<\/span>\n<span class=\"hljs-keyword\">if<\/span> ($status !== UPLOAD_ERR_OK) {\n    redirect_with_message($messages&#91;$status], FLASH_ERROR);\n}\n\n<span class=\"hljs-comment\">\/\/ validate the file size<\/span>\n$filesize = filesize($tmp);\n<span class=\"hljs-keyword\">if<\/span> ($filesize &gt; MAX_SIZE) {\n    redirect_with_message(<span class=\"hljs-string\">'Error! your file size is '<\/span> . format_filesize($filesize) . <span class=\"hljs-string\">' , which is bigger than allowed size '<\/span> . format_filesize(MAX_SIZE), FLASH_ERROR);\n}\n\n<span class=\"hljs-comment\">\/\/ validate the file type<\/span>\n$mime_type = get_mime_type($tmp);\n<span class=\"hljs-keyword\">if<\/span> (!in_array($mime_type, array_keys(ALLOWED_FILES))) {\n    redirect_with_message(<span class=\"hljs-string\">'The file type is not allowed to upload'<\/span>, FLASH_ERROR);\n}\n<span class=\"hljs-comment\">\/\/ set the filename as the basename + extension<\/span>\n$uploaded_file = pathinfo($filename, PATHINFO_FILENAME) . <span class=\"hljs-string\">'.'<\/span> . ALLOWED_FILES&#91;$mime_type];\n<span class=\"hljs-comment\">\/\/ new file location<\/span>\n$filepath = UPLOAD_DIR . <span class=\"hljs-string\">'\/'<\/span> . $uploaded_file;\n\n<span class=\"hljs-comment\">\/\/ move the file to the upload dir<\/span>\n$success = move_uploaded_file($tmp, $filepath);\n<span class=\"hljs-keyword\">if<\/span> ($success) {\n    redirect_with_message(<span class=\"hljs-string\">'The file was uploaded successfully.'<\/span>, FLASH_SUCCESS);\n}\n\nredirect_with_message(<span class=\"hljs-string\">'Error moving the file to the upload folder.'<\/span>, FLASH_ERROR);<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-22\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>How the <code>upload.php<\/code> works.<\/p>\n\n\n\n<p>1) Start the session and include the <code>flash.php<\/code> and <code>functions.php<\/code> files so that we can use the utility functions defined above:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-23\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\">session_start();\n<span class=\"hljs-keyword\">require_once<\/span> <span class=\"hljs-keyword\">__DIR__<\/span> . <span class=\"hljs-string\">'\/inc\/flash.php'<\/span>;\n<span class=\"hljs-keyword\">require_once<\/span> <span class=\"hljs-keyword\">__DIR__<\/span> . <span class=\"hljs-string\">'\/inc\/functions.php'<\/span>;<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-23\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>2) Define an array that specifies the allowed files:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-24\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\"><span class=\"hljs-keyword\">const<\/span> ALLOWED_FILES = &#91;\n   <span class=\"hljs-string\">'image\/png'<\/span> =&gt; <span class=\"hljs-string\">'png'<\/span>,\n   <span class=\"hljs-string\">'image\/jpeg'<\/span> =&gt; <span class=\"hljs-string\">'jpg'<\/span>\n];<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-24\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>3) Define a constant that specifies the max file size:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-25\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\"><span class=\"hljs-keyword\">const<\/span> MAX_SIZE  = <span class=\"hljs-number\">5<\/span> * <span class=\"hljs-number\">1024<\/span> * <span class=\"hljs-number\">1024<\/span>; <span class=\"hljs-comment\">\/\/  5MB<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-25\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>3) Define the upload directory that stores the uploaded files:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-26\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\"><span class=\"hljs-keyword\">const<\/span> UPLOAD_DIR = <span class=\"hljs-keyword\">__DIR__<\/span> . <span class=\"hljs-string\">'\/uploads'<\/span>;<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-26\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>4) Return an error message if the request method is not <code>POST<\/code> or the <code>file<\/code> does not exist in the <code>$_FILES<\/code> variable:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-27\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\">$is_post_request = strtolower($_SERVER&#91;<span class=\"hljs-string\">'REQUEST_METHOD'<\/span>]) === <span class=\"hljs-string\">'post'<\/span>;\n$has_file = <span class=\"hljs-keyword\">isset<\/span>($_FILES&#91;<span class=\"hljs-string\">'file'<\/span>]);\n\n<span class=\"hljs-keyword\">if<\/span> (!$is_post_request || !$has_file) {\n    redirect_with_message(<span class=\"hljs-string\">'Invalid file upload operation'<\/span>, FLASH_ERROR);\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-27\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>5) Get the uploaded file information including error, filename, and temporary filename:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-28\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\">$status = $_FILES&#91;<span class=\"hljs-string\">'file'<\/span>]&#91;<span class=\"hljs-string\">'error'<\/span>];\n$filename = $_FILES&#91;<span class=\"hljs-string\">'file'<\/span>]&#91;<span class=\"hljs-string\">'name'<\/span>];\n$tmp = $_FILES&#91;<span class=\"hljs-string\">'file'<\/span>]&#91;<span class=\"hljs-string\">'tmp_name'<\/span>];<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-28\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>6) Return an error message if the file was failed to upload:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-29\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\"><span class=\"hljs-keyword\">if<\/span> ($status !== UPLOAD_ERR_OK) {\n    redirect_with_message(MESSAGES&#91;$status], FLASH_ERROR);\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-29\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>7) Get the size of the file in the temporary folder and compare it with the MAX_SIZE. If the size of the uploaded file is greater than MAX_SIZE, issue an error:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-30\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\"><span class=\"hljs-comment\">\/\/ validate the file size<\/span>\n$filesize = filesize($tmp);\n<span class=\"hljs-keyword\">if<\/span> ($filesize &gt; MAX_SIZE) {\n    redirect_with_message(<span class=\"hljs-string\">'Error! your file size is '<\/span> . format_filesize($filesize) . <span class=\"hljs-string\">' , which is bigger than allowed size '<\/span> . format_filesize(MAX_SIZE), FLASH_ERROR);\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-30\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>8) Get the MIME type and compare it with the MIME type of the allowed files specified in the  ALLOWED_FILES  array; issue an error if the validation fails:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-31\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\">$mime_type = get_mime_type($tmp);\n<span class=\"hljs-keyword\">if<\/span> (!in_array($mime_type, array_keys(ALLOWED_FILES))) {\n    redirect_with_message(<span class=\"hljs-string\">'The file type is not allowed to upload'<\/span>, FLASH_ERROR);\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-31\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>9) Construct a new filename by concatenating the filename from the uploaded file with the valid file extension.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-32\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\"><span class=\"hljs-comment\">\/\/ set the filename as the basename + extension<\/span>\n$uploaded_file = pathinfo($filename, PATHINFO_FILENAME) . <span class=\"hljs-string\">'.'<\/span> . ALLOWED_FILES&#91;$mime_type];<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-32\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Note that the following <code><a href=\"https:\/\/phptutorial.net\/php-tutorial\/php-pathinfo\/\">pathinfo()<\/a><\/code> returns the filename without the extension:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-33\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\">pathinfo($filename, PATHINFO_FILENAME)<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-33\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>For example, if the <code>$filename<\/code> is <code>example.jpg<\/code>, it&#8217;ll return the <code>example<\/code> only.<\/p>\n\n\n\n<p>10) Move the file from the temp directory to the upload folder and issue an error or success message depending on the result of the  <code>move_uploaded_file()<\/code> function:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-34\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\">$filepath = UPLOAD_DIR . <span class=\"hljs-string\">'\/'<\/span> . $uploaded_file;\n\n<span class=\"hljs-comment\">\/\/ move the file to the upload dir<\/span>\n$success = move_uploaded_file($tmp, $filepath);\n\n<span class=\"hljs-keyword\">if<\/span> ($success) {\n    redirect_with_message(<span class=\"hljs-string\">'The file was uploaded successfully.'<\/span>, FLASH_SUCCESS);\n}\n\nredirect_with_message(<span class=\"hljs-string\">'Error moving the file to the upload directory.'<\/span>, FLASH_ERROR);<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-34\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p><a href=\"https:\/\/phptutorial.net\/wp-content\/uploads\/2025\/04\/upload.zip\" target=\"_blank\" rel=\"noreferrer noopener\">Download PHP File Upload Source Code<\/a><\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id='summary'>Summary <a href=\"#summary\" class=\"anchor\" id=\"summary\" title=\"Anchor for Summary\">#<\/a><\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Use the <code>input<\/code> with <code>type=\"file\"<\/code> to create a file input element and include the <code>enctype=\"multipart\/form-data\"<\/code> attribute in the form to allow the file upload.<\/li>\n\n\n\n<li>Access the uploaded file information via the <code>$_FILES<\/code> array.<\/li>\n\n\n\n<li>Never trust the information on the <code>$_FILES<\/code> except the <code>tmp_name<\/code> .<\/li>\n\n\n\n<li>Always validate the information on the <code>$_FILES<\/code> .<\/li>\n\n\n\n<li>Use the <code>move_uploaded_file()<\/code> function to move the file from the temporary directory to another folder.<\/li>\n<\/ul>\n\n\n\n<p><\/p>\n<div class=\"helpful-block-content\" data-title=\"\">\n\t<header>\n\t\t<div class=\"wth-question\">Did you find this tutorial useful?<\/div>\n\t\t<div class=\"wth-thumbs\">\n\t\t\t<button\n\t\t\t\tdata-post=\"83\"\n\t\t\t\tdata-post-url=\"https:\/\/www.phptutorial.net\/php-tutorial\/php-file-upload\/\"\n\t\t\t\tdata-post-title=\"PHP File Upload\"\n\t\t\t\tdata-response=\"1\"\n\t\t\t\tclass=\"wth-btn-rounded wth-yes-btn\"\n\t\t\t>\n\t\t\t\t<svg\n\t\t\t\t\txmlns=\"http:\/\/www.w3.org\/2000\/svg\"\n\t\t\t\t\tviewBox=\"0 0 24 24\"\n\t\t\t\t\tfill=\"none\"\n\t\t\t\t\tstroke=\"currentColor\"\n\t\t\t\t\tstroke-width=\"2\"\n\t\t\t\t\tstroke-linecap=\"round\"\n\t\t\t\t\tstroke-linejoin=\"round\"\n\t\t\t\t\tclass=\"feather feather-thumbs-up block w-full h-full\"\n\t\t\t\t>\n\t\t\t\t\t<path\n\t\t\t\t\t\td=\"M14 9V5a3 3 0 0 0-3-3l-4 9v11h11.28a2 2 0 0 0 2-1.7l1.38-9a2 2 0 0 0-2-2.3zM7 22H4a2 2 0 0 1-2-2v-7a2 2 0 0 1 2-2h3\"\n\t\t\t\t\t><\/path>\n\t\t\t\t<\/svg>\n\t\t\t\t<span class=\"sr-only\"> Yes <\/span>\n\t\t\t<\/button>\n\n\t\t\t<button\n\t\t\t\tdata-response=\"0\"\n\t\t\t\tdata-post=\"83\"\n\t\t\t\tdata-post-url=\"https:\/\/www.phptutorial.net\/php-tutorial\/php-file-upload\/\"\n\t\t\t\tdata-post-title=\"PHP File Upload\"\n\t\t\t\tclass=\"wth-btn-rounded wth-no-btn\"\n\t\t\t>\n\t\t\t\t<svg\n\t\t\t\t\txmlns=\"http:\/\/www.w3.org\/2000\/svg\"\n\t\t\t\t\tviewBox=\"0 0 24 24\"\n\t\t\t\t\tfill=\"none\"\n\t\t\t\t\tstroke=\"currentColor\"\n\t\t\t\t\tstroke-width=\"2\"\n\t\t\t\t\tstroke-linecap=\"round\"\n\t\t\t\t\tstroke-linejoin=\"round\"\n\t\t\t\t>\n\t\t\t\t\t<path\n\t\t\t\t\t\td=\"M10 15v4a3 3 0 0 0 3 3l4-9V2H5.72a2 2 0 0 0-2 1.7l-1.38 9a2 2 0 0 0 2 2.3zm7-13h2.67A2.31 2.31 0 0 1 22 4v7a2.31 2.31 0 0 1-2.33 2H17\"\n\t\t\t\t\t><\/path>\n\t\t\t\t<\/svg>\n\t\t\t\t<span class=\"sr-only\"> No <\/span>\n\t\t\t<\/button>\n\t\t<\/div>\n\t<\/header>\n\n\t<div class=\"wth-form hidden\">\n\t\t<div class=\"wth-form-wrapper\">\n\t\t\t<div class=\"wth-title\"><\/div>\n\t\t\t\n\t\t\t<textarea class=\"wth-message\"><\/textarea>\n\n\t\t\t<button class=\"btn btn-primary wth-btn-submit\">Send<\/button>\n\t\t\t<button class=\"btn wth-btn-cancel\">Cancel<\/button>\n\t\t\n\t\t<\/div>\n\t<\/div>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>In this tutorial, you will learn how to upload a single file from its storage device to the server using PHP.<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":15,"menu_order":94,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"class_list":["post-83","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/www.phptutorial.net\/wp-json\/wp\/v2\/pages\/83","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.phptutorial.net\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/www.phptutorial.net\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/www.phptutorial.net\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.phptutorial.net\/wp-json\/wp\/v2\/comments?post=83"}],"version-history":[{"count":4,"href":"https:\/\/www.phptutorial.net\/wp-json\/wp\/v2\/pages\/83\/revisions"}],"predecessor-version":[{"id":3306,"href":"https:\/\/www.phptutorial.net\/wp-json\/wp\/v2\/pages\/83\/revisions\/3306"}],"up":[{"embeddable":true,"href":"https:\/\/www.phptutorial.net\/wp-json\/wp\/v2\/pages\/15"}],"wp:attachment":[{"href":"https:\/\/www.phptutorial.net\/wp-json\/wp\/v2\/media?parent=83"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}