Last active
July 20, 2019 10:53
-
-
Save RyadPasha/cdeb607587d9812559175d10b9784570 to your computer and use it in GitHub Desktop.
Full Secure File Upload Function in PHP.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* @project: PHP File Uploader | |
* | |
* @purpose: This fuction provides a full secure file upload in PHP. | |
* @version: 1.0 | |
* | |
* | |
* @author: Mohamed Riyad | |
* @created on: 9 Jun, 2019 | |
* | |
* @url: http://ryadpasha.com | |
* @email: me@ryadpasha.com | |
* @license: GNU General Public License v3.0 | |
* | |
* @see: https://github.com/ryadpasha/PHPFileUploader | |
* | |
* Ex.: Suppose we have a posted file with field | |
* name ‘profile_pic’ ($_FILES['profile_pic']) | |
* Since it's a picture, we can validate it as follows: | |
* secureUpload('profile_pic', 'uploads/', 2000000, 'user_111112', true, true); | |
*/ | |
function secureUpload($fileField = null, $uploadPath = 'uploads/', $maxSize = 8000000, $newName = 1, $isImage = true, $checkImage = false, $allowedMimeTypes = []) { | |
// Create an array to hold any outputs: | |
$output = []; | |
if($isImage) | |
$allowedMimeTypes = | |
['jpeg'=> 'image/jpeg', | |
'jpg' => 'image/jpeg', | |
'png' => 'image/png', | |
'bmp' => 'image/bmp', | |
'gif' => 'image/gif']; | |
elseif(!is_array($allowedMimeTypes) || @count($allowedMimeTypes) < 1) | |
$allowedMimeTypes = | |
['ez'=>'application/andrew-inset','hqx'=>'application/mac-binhex40','cpt'=>'application/mac-compactpro', | |
'doc'=>'application/msword','bin'=>'application/octet-stream','dms'=>'application/octet-stream','lha'=>'application/octet-stream', | |
'lzh'=>'application/octet-stream','exe'=>'application/octet-stream','class'=>'application/octet-stream','so'=>'application/octet-stream', | |
'dll'=>'application/octet-stream','oda'=>'application/oda','pdf'=>'application/pdf','ai'=>'application/postscript','eps'=>'application/postscript', | |
'ps'=>'application/postscript','smi'=>'application/smil','smil'=>'application/smil','wbxml'=>'application/vnd.wap.wbxml','wmlc'=>'application/vnd.wap.wmlc', | |
'wmlsc'=>'application/vnd.wap.wmlscriptc','bcpio'=>'application/x-bcpio','vcd'=>'application/x-cdlink','pgn'=>'application/x-chess-pgn','cpio'=>'application/x-cpio', | |
'csh'=>'application/x-csh','dcr'=>'application/x-director','dir'=>'application/x-director','dxr'=>'application/x-director','dvi'=>'application/x-dvi','spl'=>'application/x-futuresplash', | |
'gtar'=>'application/x-gtar','hdf'=>'application/x-hdf','js'=>'application/x-javascript','skp'=>'application/x-koan','skd'=>'application/x-koan','skt'=>'application/x-koan', | |
'skm'=>'application/x-koan','latex'=>'application/x-latex','nc'=>'application/x-netcdf','cdf'=>'application/x-netcdf','sh'=>'application/x-sh','shar'=>'application/x-shar', | |
'swf'=>'application/x-shockwave-flash','sit'=>'application/x-stuffit','sv4cpio'=>'application/x-sv4cpio','sv4crc'=>'application/x-sv4crc','tar'=>'application/x-tar', | |
'tcl'=>'application/x-tcl','tex'=>'application/x-tex','texinfo'=>'application/x-texinfo','texi'=>'application/x-texinfo','t'=>'application/x-troff','tr'=>'application/x-troff', | |
'roff'=>'application/x-troff','man'=>'application/x-troff-man','me'=>'application/x-troff-me','ms'=>'application/x-troff-ms','ustar'=>'application/x-ustar', | |
'src'=>'application/x-wais-source','xhtml'=>'application/xhtml+xml','xht'=>'application/xhtml+xml','zip'=>'application/zip','au'=>'audio/basic','snd'=>'audio/basic','mid'=>'audio/midi', | |
'midi'=>'audio/midi','kar'=>'audio/midi','mpga'=>'audio/mpeg','mp2'=>'audio/mpeg','mp3'=>'audio/mpeg','aif'=>'audio/x-aiff','aiff'=>'audio/x-aiff','aifc'=>'audio/x-aiff', | |
'm3u'=>'audio/x-mpegurl','ram'=>'audio/x-pn-realaudio','rm'=>'audio/x-pn-realaudio','rpm'=>'audio/x-pn-realaudio-plugin','ra'=>'audio/x-realaudio','wav'=>'audio/x-wav', | |
'pdb'=>'chemical/x-pdb','xyz'=>'chemical/x-xyz','bmp'=>'image/bmp','gif'=>'image/gif','ief'=>'image/ief','jpeg'=>'image/jpeg','jpg'=>'image/jpeg','jpe'=>'image/jpeg', | |
'png'=>'image/png','tiff'=>'image/tiff','tif'=>'image/tif','djvu'=>'image/vnd.djvu','djv'=>'image/vnd.djvu','wbmp'=>'image/vnd.wap.wbmp','ras'=>'image/x-cmu-raster', | |
'pnm'=>'image/x-portable-anymap','pbm'=>'image/x-portable-bitmap','pgm'=>'image/x-portable-graymap','ppm'=>'image/x-portable-pixmap','rgb'=>'image/x-rgb','xbm'=>'image/x-xbitmap', | |
'xpm'=>'image/x-xpixmap','xwd'=>'image/x-windowdump','igs'=>'model/iges','iges'=>'model/iges','msh'=>'model/mesh','mesh'=>'model/mesh','silo'=>'model/mesh','wrl'=>'model/vrml', | |
'vrml'=>'model/vrml','css'=>'text/css','html'=>'text/html','htm'=>'text/html','asc'=>'text/plain','txt'=>'text/plain','rtx'=>'text/richtext','rtf'=>'text/rtf', | |
'sgml'=>'text/sgml','sgm'=>'text/sgml','tsv'=>'text/tab-seperated-values','wml'=>'text/vnd.wap.wml','wmls'=>'text/vnd.wap.wmlscript','etx'=>'text/x-setext', | |
'xml'=>'text/xml','xsl'=>'text/xml','mpeg'=>'video/mpeg','mpg'=>'video/mpeg','mpe'=>'video/mpeg','qt'=>'video/quicktime','mov'=>'video/quicktime','mxu'=>'video/vnd.mpegurl', | |
'avi'=>'video/x-msvideo','movie'=>'video/x-sgi-movie','ice'=>'x-conference-xcooltalk']; | |
else if(isset($allowedMimeTypes['0'])) $output['errors'][] = 'The allowed extensions must be used as index for each MIME type in the ‘$allowedMimeTypes’ array.'; | |
$uploadPath = rtrim($uploadPath, '/') . '/'; // Checking if path ends in '/' ... if not then tack it on. | |
// || Validation || | |
if(!$fileField) $output['errors'][] = 'Please specify a valid file field.'; | |
if(!$uploadPath) $output['errors'][] = 'Please specify a valid upload path.'; | |
if(@count($output['errors']) > 0) return $output; | |
if((!empty($_FILES[$fileField])) && ($_FILES[$fileField]['error'] == 0)) { | |
// Get file info: | |
$fileInfo = pathinfo($_FILES[$fileField]['name']); | |
$fileName = $fileInfo['filename']; | |
$fileSize = $_FILES[$fileField]['size']; | |
$fileExt = strtolower($fileInfo['extension']); | |
// Check if the file has the right extension and type: | |
if(!@isset($allowedMimeTypes[$fileExt])) $output['errors'][] = 'Invalid file extension.'; | |
if(!@in_array($_FILES[$fileField]['type'], $allowedMimeTypes)) $output['errors'][] = 'Invalid file type.'; | |
// Check that the file is not too big .. Given $maxSize in (byets). | |
if($fileSize > $maxSize) $output['errors'][] = 'File is too big. Max allowed size is: '.($maxSize / 1024).' Kb, yours is '.($fileSize / 1024).' Kb.'; | |
// If ‘$isImage’ AND ‘$checkImage’ are set to ‘true’ | |
// Then, using getimagesize(), we'll be processing the image with the GD library. | |
// If it isn’t an image, this will fail and therefor the entire upload will fail: | |
if($checkImage && $isImage){if(!getimagesize($_FILES[$fileField]['tmp_name'])) $output['errors'][] = 'Uploaded file is not a valid image.';} | |
$newFileName = ($newName === 1 ? sprintf('%s.%s', md5_file($_FILES[$fileField]['tmp_name']), $fileExt) // If ($newName = 1) <- $newFileName = Md5_file | |
: ($newName === 2 ? sprintf('%s.%s', substr(md5(microtime()),0,15), $fileExt) // If ($newName = 2) <- $newFileName = Random name | |
: ($newName === 3 ? sprintf('%s.%s', $fileName, $fileExt) // If ($newName = 3) <- $newFileName = Same name | |
: sprintf('%s.%s', $newName, $fileExt)))); // Else <- $newFileName = The name passed in ‘$newName’ | |
// Check if file already exists on server: | |
if(file_exists($uploadPath.$newFileName)) $output['errors'][] = 'A file with the same name already exists.'; | |
// Create the $uploadPath if it doesn't already exist: | |
if(!is_dir($uploadPath)) @mkdir($uploadPath) OR $output['errors'][] = 'Error creating directory: '.str_replace(['mkdir(): ','File'],['','Directory'], error_get_last()['message']); | |
// The file has not correctly validated: | |
if(@count($output['errors']) > 0) return $output; | |
if(move_uploaded_file($_FILES[$fileField]['tmp_name'], $uploadPath.$newFileName)) { | |
$output['filename'] = $newFileName; | |
$output['filepath'] = $uploadPath; | |
$output['filesize'] = $fileSize; | |
} else $output['errors'][] = 'Server error.'; | |
} else $output['errors'][] = 'No file uploaded.'; | |
return $output; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment