Skip to content

Instantly share code, notes, and snippets.

@antongorodezkiy
Forked from RalfAlbert/file_upload.php
Last active August 29, 2015 14:07
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save antongorodezkiy/10be9f726d827f920aaa to your computer and use it in GitHub Desktop.
Save antongorodezkiy/10be9f726d827f920aaa to your computer and use it in GitHub Desktop.
<?php
class File_Upload
{
/**
* Index key from upload form
* @var string
*/
public $index_key = '';
/**
* Copy of superglobal array $_FILES
* @var array
*/
public $files = array();
/**
* Array with url, filepath and mimetype after uploading
* @var array
*/
public $filedata = array();
/**
* Error object containing errors as WP_Error
* @var onject
*/
public $errors = null;
/**
* Constructor
* Setup files array and guess index key
*/
public function __construct($index_key) {
if ( isset( $_FILES ) && ! empty( $_FILES ) && isset( $_FILES[$index_key] ) && ! empty( $_FILES[$index_key] ) ) {
$this->files = array();
foreach($_FILES as $field => $_FILE) {
if (!isset($this->files[$field])) {
$this->files[$field] = array();
}
foreach($_FILE as $property_name => $properties) {
if (is_array($properties)) {
foreach($properties as $file_key => $file_property) {
if (!isset($this->files[$field][$file_key])) {
$this->files[$field][$file_key] = array();
}
$this->files[$field][$file_key][$property_name] = $file_property;
}
}
else {
if (!isset($this->files[$field])) {
$this->files[$field] = array();
}
$this->files[$field][$property_name] = $file_property;
}
}
}
if ($index_key) {
$this->index_key = $index_key;
}
else {
$this->guess_index_key();
}
}
}
/**
* Set/overwrites the index key
* Converts $name with type casting (string)
*
* @param string $name Name of the index key
* @return string ::name Name of the stored index key
*/
public function set_field_name_for_file( $name = '' ) {
$this->index_key = ( ! empty( $name ) ) ? (string) $name : '';
return $this->index_key;
}
/**
* Converts uploaded file into WordPress attachment
*
* @return boolean Whether if the attachment was created (true) or not (false)
*/
public function create_attachment($index = null){
// move the uploaded file from temp folder and create basic data
$this->filedata = $this->handle_uploaded_file($index);
// if moving fails, stop here
if ( empty( $this->filedata ) || is_wp_error( $this->filedata ) ) {
$code = 'createerror';
$msg = 'Could not create attachment';
if ( is_wp_error( $this->filedata ) ) {
$this->errors = $this->filedata;
$this->filedata = array();
$this->errors->add( $code, $msg );
} else {
$this->errors = new WP_Error( $code, $msg );
}
return $this->errors;
}
/*
* For Production
* Check if $imagedata contains the expected (and needed)
* values. Every method could fail and return malicious data!!
*/
extract( $this->filedata );
// create the attachment data array
$attachment = array(
'guid' => $url,
'post_mime_type' => $type,
'post_title' => sanitize_key( basename( $file ) ),
'post_content' => '',
'post_status' => 'inherit'
);
// insert attachment (posttype attachment)
$attach_id = wp_insert_attachment( $attachment, $file );
// you must first include the image.php file
// for the function wp_generate_attachment_metadata() to work
require_once( ABSPATH . 'wp-admin/includes/image.php' );
/*
* For Production
* Check $attach_data, wp_generate_attachment_metadata() could fail
* Check if wp_update_attachment_metadata() fails (returns false),
* return an error object with WP_Error()
*/
$attach_data = wp_generate_attachment_metadata( $attach_id, $file );
wp_update_attachment_metadata( $attach_id, $attach_data );
return $attach_id;
}
/**
* Handles the upload
*
* @return array|object $return_data Array with informations about the uploaded file on success. WP_Error object on failure
*/
protected function handle_uploaded_file($index = null) {
if ($index === null) {
// stop if something went wrong
if ( ! isset( $this->files[$this->index_key]['tmp_name'] ) || empty( $this->files[$this->index_key]['tmp_name'] ) ) {
$code = ( isset( $this->files[$this->index_key]['error'] ) ) ?
$this->files[$this->index_key]['error'] : 0;
$msg = $this->guess_upload_error( $code );
return new WP_Error( 'uploaderror', 'Upload failed with message: ' . $msg );
}
/*
* For Production
* You should really, really check the file extension and filetype ($movedfile['type'])
* on EVERY upload. If you do not, it is possible to upload EVERY kind of
* file including malicious code.
*
*/
if ( ! function_exists( 'wp_handle_upload' ) )
require_once( ABSPATH . 'wp-admin/includes/file.php' );
$movedfile = wp_handle_upload( $this->files[$this->index_key], array( 'test_form' => false ) );
return $movedfile;
}
else {
// stop if something went wrong
if ( ! isset( $this->files[$this->index_key][$index]['tmp_name'] ) || empty( $this->files[$this->index_key][$index]['tmp_name'] ) ) {
$code = ( isset( $this->files[$this->index_key][$index]['error'] ) ) ?
$this->files[$this->index_key][$index]['error'] : 0;
$msg = $this->guess_upload_error( $code );
return new WP_Error( 'uploaderror', 'Upload failed with message: ' . $msg );
}
/*
* For Production
* You should really, really check the file extension and filetype ($movedfile['type'])
* on EVERY upload. If you do not, it is possible to upload EVERY kind of
* file including malicious code.
*
*/
if ( ! function_exists( 'wp_handle_upload' ) )
require_once( ABSPATH . 'wp-admin/includes/file.php' );
$movedfile = wp_handle_upload( $this->files[$this->index_key][$index], array( 'test_form' => false ) );
return $movedfile;
}
}
/**
* Try to fetch the first index from $_FILES
*
* @return boolean Whether if a key was found or not
*/
protected function guess_index_key() {
$keys = array_keys( $_FILES );
if ( ! empty( $keys ) ) {
$this->index_key = $keys[0];
return true;
}
return false;
}
protected function guess_upload_error( $err = 0 ) {
$errcodes = array(
'Unknown error',
'The uploaded file exceeds the upload_max_filesize directive in php.ini.',
'The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form.',
'The uploaded file was only partially uploaded.',
'No file was uploaded.',
'Missing a temporary folder.',
'Failed to write file to disk.',
'A PHP extension stopped the file upload. PHP does not provide a way to ascertain which extension caused the file upload to stop; examining the list of loaded extensions with phpinfo() may help.'
);
return ( isset( $errcodes[$err] ) ) ?
$errcodes[$err] : 'Unknown error';
}
}
<?php
if ( empty ( $_FILES ) ) {
global $pagenow;
$url = admin_url( $pagenow );
?>
<!-- The data encoding type, enctype, MUST be specified as below -->
<form enctype="multipart/form-data" action="<?php echo $url; ?>" method="POST">
<!-- MAX_FILE_SIZE must precede the file input field -->
<input type="hidden" name="MAX_FILE_SIZE" value="30000" />
<!-- Name of input element determines name in $_FILES array -->
Send this file: <input name="userfile" type="file" />
<input type="submit" value="Send File" />
</form>
<?php
} else {
$imageupload = new File_Upload();
$attachment_id = $imageupload->create_attachment();
if ( is_wp_error( $attachment_id ) ) {
echo '<ol>';
foreach ( $attachment_id->get_error_messages() as $err )
printf( '<li>%s</li>', $err );
echo '</ol>';
} else {
// check if the upload was successfull
$attachment = get_post( $attachment_id );
$image_url = $attachment->guid;
printf( '<p><img src="%s"></p>', $image_url );
}
}
// multiple files
// <input type="file" name="mass-upload-field[]" />
$imageupload = new File_Upload("mass-upload-field");
foreach($_FILES['mass-upload-field']['name'] as $index => $file) {
$attachment_id = $imageupload->create_attachment($index);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment