Step By Step PHP File Upload

Upload Process

The html open form tag must have method=”post” and enctype=”multipart/form-data”.

$_FILES is an associative superglobal array for uploaded files by using the post method. If the form for uploading is submitted, we can use $_FILES arrays for validating and copying the uploaded file(s). The link for $_FILES format is here.

The file name with file extension is: $_FILES[$file_key]['name'] Here $file_key is the “name” of input with type=”file” in the form.

The file name without extension can be get with function: basename($_FILES[$file_key]['name'])

The file type (MIME) is: $_FILES[$file_key]['tmp_name'] But this type can be fake!

We can use the function getimagesize in the case of images. This function returns an array with the element “mime”. This element has value “false” if the image file type is fake. However, the image file can contain executable code such as PHP code – see this PHP Image Upload Security: How Not to Do It | NullCandy

$arr=getimagesize($_FILES[$file_key]['tmp_name']); // and then chek $arr[‘mime’]

The file extension is: $ext=strtolower(pathinfo('Path_toUpload'. $_FILES[$file_key]['name'], PATHINFO_EXTENSION); The extension can be fake too!

It is mandatory to check the file size with: $_FILES[$file_key]['size']

We can make upload with function: move_uploaded_file($_FILES['fileToUpload']['tmp_name'], $file_name) If the upload is succeded this function returns true otherwise returns false.

Additional actions as good practice

The upload directory must be out of application root.

Record the file name in the database.

The upload directory must be not readable for the user. Use instead the database.

Rename the uploaded file with an encrypted name or randomized with the current timestamp as an example: echo md5(substr(hrtime(true),5,8)); echo sha1(substr(hrtime(true),2,10));

Check if the file already exists with function: file_exists($file_name)

Set rules for users and check if the user has the right to upload.

Use Apache ForceType directive in .htaccess
"...this directive forces all matching files to be served with the content type identification given by media-type."
This prevent executing a php script in the image file.

<FilesMatch "uploads/jpg"> ForceType image/jpeg </FilesMatch> <FilesMatch "uploads/pdf"> ForceType application/octet-stream Header set Content-Disposition attachment </FilesMatch>