Welcome Guest, Not a member yet? Register   Sign In
Multiple File Uploads Failing :(
#1

[eluser]Jazzerus[/eluser]
I'm working on the admin section for a product gallery and I'm having some trouble trying to get multiple files to upload. Below is the (simplified) code and the messages I'm getting.

View:
Code:
<? echo form_open_multipart('admin/products/save'); ?>
<input type="hidden" name="MAX_FILE_SIZE" value="3145728" />
...
Product: <input type="file" name="image" class="file" id="productImage"/>
Product Thumbnail: <input type="file" name="thumbnail" class="file" id="productThumb"/>
...
<input class="save" type="submit" value="Save"><input class="cancel" type="submit" value="Cancel">
<? echo form_close(); ?>

Controller:
Code:
function products() {
    ...
    if($segment_3 == "save") {
        print_r($_FILES);
        // do some basic validation on the text fields...
        ...
        if (isset($_FILES['image']['tmp_name']) && is_uploaded_file($_FILES['image']['tmp_name'])) {
            $field_name = "image";
            $config = array();
            $config['max_width'] = 420;
            $config['max_height'] = 420;
            $img_success = $this->_handle_image_upload($config, $field_name, &$img_status);
            print_r($img_status);
        }
        if (isset($_FILES['thumbnail']['tmp_name']) && is_uploaded_file($_FILES['thumbnail']['tmp_name'])) {
            $field_name = "thumbnail";
            $config = array();
            $config['max_width'] = 129;
            $config['max_height'] = 144;
            $thm_success = $this->_handle_image_upload($config, $field_name, &$thm_status);
            print_r($thm_status);
        }
        ...
    }
    ...
}
function _handle_image_upload($config, $field_name, $status) {
    // set base configuration options for library
    $base_config = array();
    $base_config['upload_path'] = $_SERVER['DOCUMENT_ROOT'] . "/images/uploads/products";
    if ($field_name == "thumbnail") {
        $base_config['upload_path'] .= "/thumbs";
    }
    $base_config['allowed_types'] = "jpg|png|gif";
    $base_config['max_size'] = 3072;
    $config = array_merge($base_config, $config);
    $this->load->library('upload', $config);
    if ($this->upload->do_upload()) {
        $status = $this->upload->data();
        return true;
    } else {
        $status = $this->upload->display_errors();
        return false;
    }
}

And last but not least, the results of the print_r commands:
Code:
Array
(
    [image] => Array
        (
            [name] => strawberry.gif
            [type] => image/gif
            [tmp_name] => /tmp/phpgqBsl3
            [error] => 0
            [size] => 59947
        )

    [thumbnail] => Array
        (
            [name] => strawberry_thumb.gif
            [type] => image/gif
            [tmp_name] => /tmp/phpniL1EM
            [error] => 0
            [size] => 8120
        )

)

You did not select a file to upload.

You did not select a file to upload.

I'm thinking it's got to be a problem with my _handle_image_upload function. Can $this->upload->do_upload() even handle multiple uploads at once?
#2

[eluser]falkencreative[/eluser]
My impression is that do_upload() only handles one file at a time. In order to get this to work, you may need to loop through each of your form fields and use do_upload() on each one, passing in the field name each time:

Code:
$field_name = "some_field_name";
$this->upload->do_upload($field_name)
#3

[eluser]Jazzerus[/eluser]
@falkencreative A coworker pointed out the solution to me about the same time you replied.

I obviously can't read the documentation.

$this->upload->do_upload() expects the name of the field to 'userfile' and if the field is named something else, do_upload() sees nothing.

I modified my _handle_image_upload function to add $field_name to the do_upload function and now it almost works perfectly.

Code:
function _handle_image_upload($config, $field_name, $status) {
    ...
    if ($this->upload->do_upload($field_name)) {
    ...
    }
}

The print_r commands now yield:
Code:
Array
(
    [image] => Array
        (
            [name] => strawberry.gif
            [type] => image/gif
            [tmp_name] => /tmp/phpuxvLHL
            [error] => 0
            [size] => 59947
        )

    [thumbnail] => Array
        (
            [name] => strawberry_thumb.gif
            [type] => image/gif
            [tmp_name] => /tmp/phpmcwZpg
            [error] => 0
            [size] => 8120
        )

)
Array
(
    [file_name] => strawberry.gif
    [file_type] => image/gif
    [file_path] => /home/(user)/public_html/images/uploads/products/
    [full_path] => /home/(user)/public_html/images/uploads/products/strawberry.gif
    [raw_name] => strawberry
    [orig_name] => strawberry.gif
    [file_ext] => .gif
    [file_size] => 58.54
    [is_image] => 1
    [image_width] => 420
    [image_height] => 315
    [image_type] => gif
    [image_size_str] => width="420" height="315"
)
Array
(
    [file_name] => strawberry.gif
    [file_type] => image/gif
    [file_path] => /home/(user)/public_html/images/uploads/products/
    [full_path] => /home/(user)/public_html/images/uploads/products/strawberry.gif
    [raw_name] => strawberry
    [orig_name] => strawberry.gif
    [file_ext] => .gif
    [file_size] => 58.54
    [is_image] => 1
    [image_width] => 420
    [image_height] => 315
    [image_type] => gif
    [image_size_str] => width="420" height="315"
)

The problem is now that the do_upload() function performs the upload manipulation twice. In other words, the second time that my _handle_image_upload() function is called, the new data is being ignored by the library and the data from the first call is being used.
#4

[eluser]Jazzerus[/eluser]
Nevermind, it is working correctly.

In my code I had print_r($img_status); twice instead of print_r($img_status); for the first code block and print_r($thm_status); for the second.

Big Grin I'm happy now.
#5

[eluser]falkencreative[/eluser]
Perfect, glad you got it working. And if I have to upload multiple items at one time, I'll have a better idea of how to go about it. Wink
#6

[eluser]Jazzerus[/eluser]
I noticed one more problem with the code I had. For some reason, the first time the library was loaded, it cached the $config['upload_path'], so the thumbnail was not going into the right directory, even though I was passing a new value for $config['upload_path']. This appeared to be the only $config[] value that got cached. Additionally the filename was getting cached.

The main image was supposed to go into /images/uploads/products/ and it was.
The thumbnail was supposed to go into /images/uploads/products/thumbs/ but instead it was going into the main image directory instead and even though it was using the thumbnail file, it was using the same filename as the main image (but simply appending the file extension (myimage.gif would become myimage.gif.gif)).

The only solution I could think of to solve this would be to somehow unload the library and load it up again with the new settings, but there is no $this->unload->library('upload') or $this->unload('upload'). (Maybe in a future version?)

Fortunately, there is a solution. The CI Loader class (the object that is called whenever you do a $this->load-> command) has a third argument that can be passed to it when loading a library:

Code:
$this->load->library('class_name', $config, 'object name');

The third argument allows you to set a name for the object that is instantiated. By creating a new object the second time the _handle_image_upload function is called, the new $config['upload_path'] is used.

My _handle_image_upload function now looks like this:
Code:
function _handle_image_upload($config, $field_name, $status) {
    // set base configuration options for library
    $base_config = array();
    $base_config['allowed_types'] = "jpg|png|gif";
    $base_config['max_size'] = 3072;
    $config = array_merge($base_config, $config);
    if (!isset($this->upload)) {
        $this->load->library('upload', $config);
        $obj_name = "upload";
    } else {
        $this->load->library('upload', $config, "upload_2");
        $obj_name = "upload_2";
    }
    if ($this->$obj_name->do_upload($field_name)) {
        $status = $this->$obj_name->data();
        return true;
    } else {
        $status = $this->$obj_name->display_errors();
        return false;
    }
}




Theme © iAndrew 2016 - Forum software by © MyBB