Welcome Guest, Not a member yet? Register   Sign In
Single, Multiple and Multiple array upload library
#1

[eluser]e-mike[/eluser]
Hello, I read a lot of posts but can't find an all-in-one solution for the folowing:

Single file solution: (standard solution and works just fine)

Code:
<form action="/upload_files/upload_single_file" method="post" enctype="multipart/form-data">
<input type="file" name="single_file" value="" />
<input type="submit" name="" value="Upload" />
</form>

Multiple file solution: (three file example)

Code:
<form action="/upload_files/upload_multiple_files" method="post" enctype="multipart/form-data">
<input type="file" name="file_1" value="" />
<input type="file" name="file_2" value="" />
<input type="file" name="file_3" value="" />
<input type="submit" name="" value="Upload" />
</form>

Multiple file array solution: (three file example, see attachement for jquery version)

Code:
<form action="/upload_files/upload_array_files" method="post" enctype="multipart/form-data">
<input type="file" name="files[]" value="" />
<input type="file" name="files[]" value="" />
<input type="file" name="files[]" value="" />
<input type="submit" name="" value="Upload" />
</form>

Please see attached controller file example. Just put in controllers and run /upload_files

I need a library to handle these three very simple ways of file upload. This can be a MY_Upload to extend CI_Upload or better a new default CI_Upload. The current only simple way to do the last two methods is the way this forum does it "To attach more than one item click preview after choosing a file". Can anyone help me reprogram the default Upload library and hopefully Ellislab will use it as default in future versions, or help me extend the default library in a way it will still work in future versions of the default Upload library?

See post #3 for new version and first solution of the library...
#2

[eluser]TheFuzzy0ne[/eluser]
This is on my list of things to, but unfortunately, it's close to the bottom. I think the best place to start is with the concept, and how it should work. Coding it should be a breeze.
#3

[eluser]TheFuzzy0ne[/eluser]
This might get you started: http://www.webresourcesdepot.com/tag/cod...framework/
#4

[eluser]e-mike[/eluser]
Thanks TheFuzzy0ne, for your input.

I did not use their way because I like to use the simple html way. I rebuild the Upload script to do everything in the first post. I even made it better, you can even use a combination of multiple upload with and multiple array upload. You can even make global and file specific config. The use of the original script stays exactly the same but now you can do more than that, multiple and multiple array.

The only thing I still have to think of, is the way error handling works. For now you get the original errors with multiple upload. Which means it wont tell you which files got an error. So if you have an error in one of the uploading files you will return to the form like the original way and give the errors, but the good uploads will be done. This last thing you can think of removing the error-less files or make a choice of only uploading when all are good. I did not build in this feature. What do you think? I like the form validation class, it would be nice to have a similar functionality in the upload class as well.

Check the controller and the class, put the controller in controllers and the class in your application libraries (not system libraries) to test. The class is a CI_Upload class and will not use the default class in the system libraries folder, but overrule it.

I like people to test and give some good feedback to make the script for the community better. Get a good look at the controller, I have commented various optional methods of doing things. A lot of things are possible.

Single file solution: (standard solution and works just fine)

Code:
// Controller

$config['upload_path']   = './uploads/';
$config['allowed_types'] = 'gif|jpg';
$config['encrypt_name']  = true;

$this->load->library('upload',$config);

#if (!$this->upload->do_upload()) // default input name userfile
if (!$this->upload->do_upload('single_file')) // input name (type file)
{
    $error = array('error' => $this->upload->display_errors());
    $this->load->view('upload_form',$error);
}    
else
{
    #$data = array('upload_data' => $this->upload->data()); // default all
    $data = array('upload_data' => $this->upload->data('single_file')); // [new] input name (type file)
    $this->load->view('upload_success',$data);
}

// View

<form action="/upload_files/upload_single_file" method="post" enctype="multipart/form-data">
<input type="file" name="single_file" value="" />
<input type="submit" name="" value="Upload" />
</form>

Multiple file solution: (three file example)

Code:
// Controller

// Global
$config['upload_path']   = './uploads/';
$config['allowed_types'] = 'gif|jpg';
$config['encrypt_name']  = true;

// File specific (overrule global and optional)
$config['file_2']['upload_path']   = './uploads/other/';
$config['file_2']['allowed_types'] = 'doc|pdf';
$config['file_2']['encrypt_name']  = true;

$this->load->library('upload',$config);

#if (!$this->upload->do_upload()) // default input name userfile[]
#if (!$this->upload->do_upload('file_1,file_2,file_3')) // csv of input names (type file)
if (!$this->upload->do_upload(array('file_1','file_2','file_3'))) // array of input names (type file)
{
    $error = array('error' => $this->upload->display_errors());
    $this->load->view('upload_form',$error);
}    
else
{
    #$data = array('upload_data' => $this->upload->data()); // default all
    #$data = array('upload_data' => $this->upload->data('file_1,file_2,file_3')); // csv
    $data = array('upload_data' => $this->upload->data(array('file_1','file_2','file_3'))); // array
    $this->load->view('upload_success',$data);
}

// View

<form action="/upload_files/upload_multiple_files" method="post" enctype="multipart/form-data">
<input type="file" name="file_1" value="" />
<input type="file" name="file_2" value="" />
<input type="file" name="file_3" value="" />
<input type="submit" name="" value="Upload" />
</form>

Multiple file array solution: (three file example, see attachement for jquery version)

Code:
// Controller

// config and handling exactly the same as single file example

// the output of data is different

Array
(
    [file_name] => Array
        (
            [0] => 8dd9faf4e710e12fec549019183e486a.JPG
            [1] => d0d1ee59d28db82ce4a92418ac655642.JPG
            [2] => 28feb3672a5fbcc6b5745f52f574d034.JPG
        )
...

// View

<form action="/upload_files/upload_array_files" method="post" enctype="multipart/form-data">
<input type="file" name="files[]" value="" />
<input type="file" name="files[]" value="" />
<input type="file" name="files[]" value="" />
<input type="submit" name="" value="Upload" />
</form>

I hope someone have some good feedback and I hope that this method or something like it will be default in the next CI versions. I also hope that someone can make the error validation something like form validation.

If you find some bugs, feel free to post them.

The class is a rewrite of the 1.7.1 version.

Mike
#5

[eluser]LuckyFella73[/eluser]
Hi Mike,

I checked out your code - thanks for this contribution!!

I slightly modified the code to my needs, but there is
one thing left I'm not happy with:
In case the user is uploading only one file you need
different code to get the upload_data compared to a
multiple files upload:
Code:
<?php
if ( isset($data['upload_data']['file_1']['file_name']) OR isset($data['upload_data']['file_2']['file_name']) OR isset($data['upload_data']['file_3']['file_name']) )
{
    # multiple files:
    foreach ($data['upload_data'] AS $data)
    {
        echo("filename: ".$data['file_name']."<br />");
        echo("width: ".$data['image_width']." px<br />");
        echo("height: ".$data['image_height']." px");
    }
}
elseif ( isset($data['upload_data']['file_name']) AND strlen($data['upload_data']['file_name'])>1 )
{
    # single file:
    echo($data['upload_data']['file_name']."<br />");
    echo($data['upload_data']['image_width']." px<br />");
    echo($data['upload_data']['image_height']." px");
}
?&gt;

What I did to make the setup a bit easier (number of files to upload
varies):
Code:
&lt;?php
$files_available = array();
$files_max = 3;
for ( $i=1; $i<=$files_max; $i++ )
{
    if(isset($_FILES['file_'.$i]) && !empty($_FILES['file_'.$i]['name']))
    {
        array_push($files_available,'file_'.$i);
    }
}

// and later:
if (!$this->upload->do_upload($files_available))
{
    // ...
    $data['upload_data'] = array('upload_data' => $this->upload->data($files_available)); // array
    $this->load->view('upload_form',$error);
}
else
{
    // ...
}
?&gt;
This way you only have to change one value to set up the number of possible
fileuploads.

What I'm struggling with ( I hope someone can help me out with this ):
Like mentioned before accessing the upload data is not the same when
uploading one or multiple files. What I do now (seems not to be the best
solution ..):
Code:
&lt;?php
if ( isset($data['upload_data']['file_1']['file_name']) OR isset($data['upload_data']['file_2']['file_name']) OR isset($data['upload_data']['file_3']['file_name']) )
{
    # multiple files upladed:
    foreach ($data['upload_data'] AS $data)
    {
        // see code above
    }
}
elseif ( isset($data['upload_data']['file_name']) AND strlen($data['upload_data']['file_name'])>1 )
{
    # single file uploaded:
    // ...
}
?&gt;
I don't like the "if" line and wonder how to set it up dynamically regarding
to the $files_available array. Any ideas?
#6

[eluser]e-mike[/eluser]
Hi LuckyFella73,

Thanks... But you don't make it any easier. file_1, file_2, file_3 are example names... These could be apples, pears, bananas... or the second method (array form) fruit[], fruit[], fruit[]...

&lt;input type="file" name="apples" value="" /&gt;
&lt;input type="file" name="pears" value="" /&gt;
&lt;input type="file" name="bananas" value="" /&gt;

or

&lt;input type="file" name="fruit[]" value="" /&gt;
&lt;input type="file" name="fruit[]" value="" /&gt;
&lt;input type="file" name="fruit[]" value="" /&gt;

All the info is stored in data. Only with the second method you will get a multi array, also with one file uploaded.

Cheers, Mike
#7

[eluser]nstokes[/eluser]
@e-mike -

I've grabbed this, and it works beautifully, thanks! I do run into trouble however when there is NO file attached (where the file is not required in the form). It's not handling it properly. Throwing errors because it's looking for a file, but one isn't there... Any ideas?

Thanks again for your efforts on this!
#8

[eluser]e-mike[/eluser]
Have a look at the code if you have a solution, post it here...
#9

[eluser]nstokes[/eluser]
I think I found the problem with the library not functioning properly when no file was selected for upload. I added something that worked for me, but I'm definitely not a PHP guru, so there is likely a better solution out there. This one works for me...

In the do_upload() method I set a check right at the beginning, to see if the file had a name, if not, then I return false.

Code:
function do_upload($fields = 'userfile')
    {
        $return = TRUE;
        
        //I added these next 5 lines
                if ( $_FILES[$fields]['name'][0] == '')
        {
            $this->set_error('upload_no_file_selected');
            return FALSE;
        }

If someone has a better solution, please I'd love to hear and implement it!
#10

[eluser]e-mike[/eluser]
do_upload is also used for single upload... with your solution single upload is disabled...

and if no file is filled in, there is no array entry (check this with print_r($_FILES))




Theme © iAndrew 2016 - Forum software by © MyBB