To upload a file or files, the enctype for a form must be 'multipart/form_data':
enctype
<form ... enctype="multipart/form-data"> <input type="file" name="x" multiple> ...
The input presents as a file label with a button that when clicked opens a file selector dialog that allows selecting a filename. The (optional) multiple attribute on the input type=file input allows the user to select more than one file for uploading.
type=file
A file does not appear the $_POST or $_GET maps, but instead in the $_FILES super-global:
$_POST
$_GET
$_FILES
$_FILES['x']
where 'x' == name of the file input element. If 'x' allows multiple files to be uploaded, then $_FILES['x']['__'] is an array. 'x' can also be in array notation:
'x'
$_FILES['x']['__']
<input type=file name='x[]'> <input type=file name='x[]'> ...
$_FILES['x']['name']
$_FILES['x']['type']
$_FILES['x']['size']
$_FILES['x']['tmp_name']
$_FILES['x']['error']
<?php $uploaddir = '/var/www/uploads/'; $uploadfile = $uploaddir . basename($_FILES['userfile']['name']); echo '<pre>'; if (move_uploaded_file($_FILES['userfile']['tmp_name'], $uploadfile)) { echo "File is valid, and was successfully uploaded.\n"; } else { echo "Possible file upload attack!\n"; } echo 'Here is some more debugging info:'; print_r($_FILES); print "</pre>"; ?>
Consider using a hash for the file-name on the server. This prevents file-name attacks and allows for easier de-duplication. $uploadfile = $uploaddir . sha1_file($_FILES['x']['tmp_name'])
<?php header('Content-Type: text/plain; charset=utf-8'); try { // Undefined | Multiple Files | $_FILES Corruption Attack // If this request falls under any of them, treat it invalid. if ( !isset($_FILES['upfile']['error']) || is_array($_FILES['upfile']['error']) ) { throw new RuntimeException('Invalid parameters.'); } // Check $_FILES['upfile']['error'] value. switch ($_FILES['upfile']['error']) { case UPLOAD_ERR_OK: break; case UPLOAD_ERR_NO_FILE: throw new RuntimeException('No file sent.'); case UPLOAD_ERR_INI_SIZE: case UPLOAD_ERR_FORM_SIZE: throw new RuntimeException('Exceeded filesize limit.'); default: throw new RuntimeException('Unknown errors.'); } // You should also check filesize here. if ($_FILES['upfile']['size'] > 1000000) { throw new RuntimeException('Exceeded filesize limit.'); } // DO NOT TRUST $_FILES['upfile']['mime'] VALUE !! // Check MIME Type by yourself. $finfo = new finfo(FILEINFO_MIME_TYPE); if (false === $ext = array_search( $finfo->file($_FILES['upfile']['tmp_name']), array( 'jpg' => 'image/jpeg', 'png' => 'image/png', 'gif' => 'image/gif', ), true )) { throw new RuntimeException('Invalid file format.'); } // You should name it uniquely. // DO NOT USE $_FILES['upfile']['name'] WITHOUT ANY VALIDATION !! // On this example, obtain safe unique name from its binary data. if (!move_uploaded_file( $_FILES['upfile']['tmp_name'], sprintf('./uploads/%s.%s', sha1_file($_FILES['upfile']['tmp_name']), $ext ) )) { throw new RuntimeException('Failed to move uploaded file.'); } echo 'File is uploaded successfully.'; } catch (RuntimeException $e) { echo $e->getMessage(); } ?>