1
votes

I'm developing a multi-file upload via ajax (old school, not Jquery). I actually did finally manage to get it to work. Trouble is, I had to comment out a line in the System/Library/Upload file, which doesn't sound like a recommended way of fixing the problem.

With the line uncommented, and if I output the upload->display_errors(), I get a Unsupported operand types in...system/libraries/Upload.php on line 496 error message.

Line 496 of system/libraries/Upload is:

// Convert the file size to kilobytes
    if ($this->file_size > 0)
    {
        $this->file_size = round($this->file_size/1024, 2);// <- this line
    }

If I comment out the line like this, I don't get an error and the file uploads correctly:

// Convert the file size to kilobytes
    if ($this->file_size > 0)
    {
        //$this->file_size = round($this->file_size/1024, 2);
    }

This is my basic controller, called "Uploader" so as not to be confused with CI's Library->Upload (I copied this class, and for some reason the author decided to name his class "Upload", and also decided to name the function "do_upload", which is kind of confusing because those are the names CodeIgniter uses for its upload class and do_upload function). As you can see I commented out the max_size parameter in the $config array:

class Uploader extends CI_Controller {

function __construct()
    {
            parent::__construct();
    }

private $data = array();
private $params = array();


public function index()
{
    echo "This is the index!";
}


    public function do_upload()
    {
        echo "<p>upload controller:</p>";
        $config = $this->set_upload_options();
        $this->load->library('upload',$config);

        echo "<pre>";
        print_r($_FILES);

        $files = $_FILES;
        $cpt = count($_FILES['photos']['name']);
        $data = array();
        $photos = "photos";
        for($i=0; $i<$cpt; $i++)
        {           
            $_FILES['photos']['name']= $files['photos']['name'][$i];
            $_FILES['photos']['type']= $files['photos']['type'][$i];
            $_FILES['photos']['tmp_name']= $files['photos']['tmp_name'][$i];
            $_FILES['photos']['error']= $files['photos']['error'][$i];
            $this->upload->initialize($config);
            if (!$this->upload->do_upload($photos)) {
                $error = array('error' => $this->upload->display_errors());
                foreach($error as $err)
                {
                    echo "<p>".$err."</p>";
                }
            }
        }
        $data['count'] = $i;
        echo $data['count'];
        return $data;

    }

    private function set_upload_options()
    {   
        //upload an image options
        $config = array();
        $config['upload_path']   = FCPATH . 'assets_/images/assets/experimental/';
        $config['allowed_types'] = 'gif|jpg|png';
        //$config['max_size']      = '0';
        $config['overwrite']     = TRUE;

        return $config;
    }

}

Should I just let sleeping dogs lie? Or am I just duct taping over a problem that's likely to come back and bite me?

UPDATE: After trying to output some of the `$this->file_size(), I discovered it was being passed as an array, so naturally an array can't be an operand.

For now I changed that if block in the system->libraries->upload file to this, a for loop which assigns a new $this->file_size according to the iterated $this->file_size[$i] within the loop. This might be the answer, but I'll wait for others to contribute before answering my own question:

        // Convert the file size to kilobytes
    if ($this->file_size > 0)
    {
                if(is_array($this->file_size)){
                    for($i=0;$i<count($this->file_size);$i++)
                    {
                        $this->file_size[$i] = round( $this->file_size[$i] / 1024, 2 );
                    }
                }else{
                    $this->file_size = round($this->file_size/1024, 2);
                }
    }
2

2 Answers

0
votes

I know why the problem occurs, and I know what to do to fix it. The problem is hinted at in the first sentence of my description, "multi-file upload".

As I already noted, the "Unsupported operand" is none other than file_size being an array, rather than a simple integer. How did it get to be an array to begin with?

You see, the $_FILES object becomes an array of arrays because I'm uploading multiple picture files, rather than a single file, so an array rather than a simple integer is passed to the System->Libraries->Upload class, lines 494 to 497,

if ($this->file_size > 0)
{
      $this->file_size = round($this->file_size/1024, 2);
}

$this->file_size becomes an array, which means it's no longer a simple operand...$this->file_size is the unsupported operand!

Of course we can't settle for "well, I guess you just shouldn't upload multiple files all at the same time." We NEED to be allowed to upload multiple files at one time. It's a requirement.

I tried moving the $this->upload->initialize($this->set_upload_options()); line within the for loop so that the upload $config would be set per file, but I was still getting this error. I'm sure there's still a more elegant solution out there, but for now modifying the if block starting at line 494 in System/Libraries/Upload.php seems bullet proof:

    if ($this->file_size > 0)
    {
                if(is_array($this->file_size)){
                    for($i=0;$i<count($this->file_size);$i++)
                    {
                        $this->file_size[$i] = round( $this->file_size[$i] / 1024, 2 );
                    }
                }else{
                    $this->file_size = round($this->file_size/1024, 2);
                }
    }

Now you can pass a simple file_size or even a file_size as an array (because you tried to upload multiple files), and this works.

And make sure your $config array looks something like this, where the 0 in $config['max_size'] = 0; and not $config['max_size'] = '0';

        private function set_upload_options()
    {   
        //upload an image options
        $config = array();
        $config['upload_path']   = FCPATH . 'assets_/images/assets/experimental/';
        $config['allowed_types'] = 'gif|jpg|png';
        $config['max_size']      = 0;
        $config['overwrite']     = TRUE;

        return $config;
    }

Apparently if it's '0' and not 0 it doesn't get evaluated properly.

0
votes

Please check system\core\Common.php

function &get_mimes()
    {
        static $_mimes;

        if (empty($_mimes))
        {
            if (file_exists(APPPATH.'config/'.ENVIRONMENT.'/mimes.php'))
            {
                $_mimes = include(APPPATH.'config/'.ENVIRONMENT.'/mimes.php');
            }
            elseif (file_exists(APPPATH.'config/mimes.php'))
            {
                $_mimes = include(APPPATH.'config/mimes.php');
            }
            else
            {
                $_mimes = array();
            }
        }

        return $_mimes;
    }

Please check your mimes.php(in config folder) according to codeigniter environment(Development/Production). You should move mimes.php in your environment folder(Development/Production).