Welcome Guest, Not a member yet? Register   Sign In
MY_Upload to work with Flash-Uploads (application/octet-stream)
#1

[eluser]Christian Rößler[/eluser]
i saw som threads about this earlyer but wanted to post a complete description to handle the issue. so here it is:

Put this code into a new file called 'MY_Upload.php' into application/librarys!
Code:
<?php
/**
* Extended / Overloaded CI-Upload Class to handle Flash-Form-Uploaded Images via Application/octet-stream
*
*/
if (!defined('BASEPATH')) exit('No direct script access allowed');


/**
* Extends the CodeIgniter Upload-Class
*/
class MY_Upload extends CI_Upload
{
    // determines whether to use application/octet-stream for image-processing...
    public $is_flash_upload = FALSE;
    
    
    /**
     * Constructor
     *
     * @access    public
     */
    function MY_Upload($props = array())
    {
        if (count($props) > 0)
        {
            $this->initialize($props);
        }
        
        log_message('debug', 'MY_Upload Class Initialized');
    }
    //
    
    
    /**
     * initializes the upload-class by settings some properties given in a config-array as parameter
     *
     * there is only one change in this method:
     *   is_flash_upload
     * this property determines whether to handle a file uploaded by flash as application/octet-stream
     * as a image or not.
     */
    public function initialize($config = array())
    {
        $defaults = array(
            'max_size'            => 0,
            'max_width'            => 0,
            'max_height'        => 0,
            'allowed_types'        => "",
            'file_temp'            => "",
            'file_name'            => "",
            'orig_name'            => "",
            'file_type'            => "",
            'file_size'            => "",
            'file_ext'            => "",
            'upload_path'        => "",
            'overwrite'            => FALSE,
            'encrypt_name'        => FALSE,
            'is_image'            => FALSE,
            'image_width'        => '',
            'image_height'        => '',
            'image_type'        => '',
            'image_size_str'    => '',
            'error_msg'            => array(),
            'mimes'                => array(),
            'remove_spaces'        => TRUE,
            'xss_clean'            => FALSE,
            'temp_prefix'        => "temp_file_",
            'is_flash_upload'   => FALSE   // <------------------  this parameter is new!
        );
        
        foreach ($defaults as $key => $val)
        {
            if (isset($config[$key]))
            {
                $method = 'set_'.$key;
                if (method_exists($this, $method))
                {
                    $this->$method($config[$key]);
                }
                else
                {
                    $this->$key = $config[$key];
                }            
            }
            else
            {
                $this->$key = $val;
            }
        }
    }
    //
    
    
    
    
    
    /**
     * when using a flash for file-uploads, the file is sent as application/octet-stream
     * and CI by default cannot determine whether the file really is a image.
     *
     * TODO: This function implements a new feature to determine whether the uploaded file
     * is a image by a simple header-check. this is enabled only when the class-property
     * is_flash_upload is set to TRUE (or 1).
     *
     */
    public function is_image()
    {
        $png_mimes;
        $jpeg_mimes;
        
        if($this->is_flash_upload)
        {
            log_message('debug', 'MY_Upload->is_image(): Adding application/octet-stream as valid image-mime-type and doing some headerchecks to verify that.');
            
            // just added the ugly flash-mime type application/octet-stream to the array
            $png_mimes  = array('image/x-png', 'application/octet-stream');
            $jpeg_mimes = array('image/jpg', 'image/jpe', 'image/jpeg', 'image/pjpeg', 'application/octet-stream');
        }
        else
        {
            // IE will sometimes return odd mime-types during upload, so here we just standardize all
            // jpegs or pngs to the same file type.
            $png_mimes  = array('image/x-png');
            $jpeg_mimes = array('image/jpg', 'image/jpe', 'image/jpeg', 'image/pjpeg');
        }
        
        if (in_array($this->file_type, $png_mimes))
        {
            $this->file_type = 'image/png';
        }
        
        if (in_array($this->file_type, $jpeg_mimes))
        {
            $this->file_type = 'image/jpeg';
        }
        
        if($this->is_flash_upload)
        {
            $img_mimes = array(
                            'image/gif',
                            'image/jpeg',
                            'image/png',
                            'application/octet-stream'
                           );
        }
        else
        {
            $img_mimes = array(
                            'image/gif',
                            'image/jpeg',
                            'image/png',
                           );
        }
        
        return (in_array($this->file_type, $img_mimes, TRUE)) ? TRUE : FALSE;
    }
    //
    
}
?&gt;

What you also need to do is adding the application/octet-stream into
Code:
application/config/mimes.php
as follows:
Code:
$mimes = array(    'hqx'    =>    'application/mac-binhex40',
...
...
'jpeg'    =>    array('image/jpeg', 'image/pjpeg', 'application/octet-stream'),
'jpg'    =>    array('image/jpeg', 'image/pjpeg', 'application/octet-stream'),
'jpe'    =>    array('image/jpeg', 'image/pjpeg', 'application/octet-stream'),
'png'    =>    array('image/png',  'image/x-png', 'application/octet-stream'),
...
...
Otherwise you cannot upload those files via flash and an error will be thrown by ci.
#2

[eluser]Christian Rößler[/eluser]
The only thing left is to determine whether the uploaded file is a image. I want to do this by opening the uplaoded file and read in the first few bytes and compare them with well known jpg + png + ... headers.

I could need help in this point ;-)

Feel free to modify this lib or give me some improvement-hints or tips how to 100% determine whether i have uploaded an image.

Here is a example usage:
(regard the additional+new parameter in the config-array and the extra parameter in do_upload())
Code:
public function index()
{
            $this->load->library('image_lib');
            $this->load->library('upload');
            
            // set up some stuff for the uploader
            $aCfg = array();
            $aCfg['upload_path']     = '/a/dir/with/write/permissions';
            $aCfg['allowed_types']   = 'jpg|bmp|png';
            $aCfg['max_size']        = '512';
            $aCfg['encrypt_name']    = TRUE;
            $aCfg['is_flash_upload'] = TRUE; // i do have a flash-upload with application/octet-stream instead of image/jpg
            $this->upload->initialize($aCfg);
            

            
            // filedata is the name of the file-input field / ie. form
            if ( $this->upload->do_upload('Filedata') == FALSE )
            {
                // there is an error when uploading the file
                log_message('error', 'Flas Upload: error uploading the image: '.$this->upload->display_errors());
            }
}



Later on you are able to process to uploaded file (image) via the image lib as follows:
(There is no magic code going on here. do it as described in the docs!)
Code:
// get an array containing all of the data related to the file i've uploaded
$aImageData = $this->upload->data();

$aCfg = array();
$aCfg['image_library']  = 'GD2';
$aCfg['source_image']     = 'name/of/the/uploaded/image.jpg';
$aCfg['quality']        = '100%';
$aCfg['width']          = '500';
$aCfg['height']         = '440';
$aCfg['new_image']    = 'name/of/the/new/and/resized/image';
$aCfg['maintain_ratio'] = TRUE;

// reset the library...
$this->image_lib->clear();
            
// and re-initialize with the new settings
$this->image_lib->initialize($aCfg);
            
// finally resize the image
if( $this->image_lib->resize() == FALSE )
{
                // an error occured while resizing the image!
                log_message('error', 'Flash imageupload: error manipulating the uploaded image (resize)');
}
#3

[eluser]Ignacio[/eluser]
Good good, excelent.

But I don't know why, I'm uploading a jpg pic and FileType retrieve me image/png.

The problem is here:

Code:
if (in_array($this->file_type, $png_mimes))
{
    $this->file_type = 'image/png';
}

Any way to solve this?
#4

[eluser]Ignacio[/eluser]
I did a hack for the upload library, I'm getting the filetype with exif data (exiftool), check this: http://ellislab.com/forums/viewthread/76751/
#5

[eluser]kallus[/eluser]
I wrote a couple of lines of code that uses fileinfo to identify a more specific mime type for files of type application/octet-stream, maybe someone finds it useful. http://ellislab.com/forums/viewthread/81308/




Theme © iAndrew 2016 - Forum software by © MyBB