Part of the EllisLab Network
   
1 of 2
1
Single, Multiple and Multiple array upload library
Posted: 29 March 2009 10:36 AM   [ Ignore ]  
Grad Student
Rank
Total Posts:  37
Joined  03-24-2009

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)

<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)

<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)

<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…

Profile
 
 
Posted: 29 March 2009 10:53 AM   [ Ignore ]   [ # 1 ]  
Sr. Research Associate
Avatar
RankRankRankRankRank
Total Posts:  3894
Joined  04-25-2008

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.

 Signature 

Remember the 8 Ps: Perfect Planning and Prior Preparation Prevents Piss-Poor Performance.


Not sure where to start with your project? Need some inspiration? Check out my CodeIgniter Resources thread

Profile
 
 
Posted: 29 March 2009 11:05 AM   [ Ignore ]   [ # 2 ]  
Sr. Research Associate
Avatar
RankRankRankRankRank
Total Posts:  3894
Joined  04-25-2008

This might get you started: http://www.webresourcesdepot.com/tag/codeigniter-framework/

 Signature 

Remember the 8 Ps: Perfect Planning and Prior Preparation Prevents Piss-Poor Performance.


Not sure where to start with your project? Need some inspiration? Check out my CodeIgniter Resources thread

Profile
 
 
Posted: 31 March 2009 05:06 AM   [ Ignore ]   [ # 3 ]  
Grad Student
Rank
Total Posts:  37
Joined  03-24-2009

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)

// 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)

// 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)

// 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

File Attachments
Library_Upload.php.zip  (File Size: 7KB - Downloads: 1454)
controller_upload_files.php.zip  (File Size: 2KB - Downloads: 1265)
Profile
 
 
Posted: 06 May 2009 05:13 AM   [ Ignore ]   [ # 4 ]  
Research Assistant
Avatar
RankRankRank
Total Posts:  774
Joined  03-25-2006

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:

<?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'])>)
{
    
# single file:
    
echo($data['upload_data']['file_name']."<br />");
    echo(
$data['upload_data']['image_width']." px<br />");
    echo(
$data['upload_data']['image_height']." px");
}
?> 

What I did to make the setup a bit easier (number of files to upload
varies):

<?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
{
    
// ...
}
?> 

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 ..):

<?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'])>)
{
    
# single file uploaded:
    // ...
}
?> 

I don’t like the “if” line and wonder how to set it up dynamically regarding
to the $files_available array. Any ideas?

Profile
 
 
Posted: 27 May 2009 09:35 AM   [ Ignore ]   [ # 5 ]  
Grad Student
Rank
Total Posts:  37
Joined  03-24-2009

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[]...

<input type=“file” name=“apples” value=”” />
<input type=“file” name=“pears” value=”” />
<input type=“file” name=“bananas” value=”” />

or

<input type=“file” name=“fruit[]” value=”” />
<input type=“file” name=“fruit[]” value=”” />
<input type=“file” name=“fruit[]” value=”” />

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

Profile
 
 
Posted: 28 May 2009 04:03 PM   [ Ignore ]   [ # 6 ]  
Summer Student
Total Posts:  12
Joined  12-19-2008

@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!

Profile
 
 
Posted: 28 May 2009 04:16 PM   [ Ignore ]   [ # 7 ]  
Grad Student
Rank
Total Posts:  37
Joined  03-24-2009

Have a look at the code if you have a solution, post it here…

Profile
 
 
Posted: 28 May 2009 04:48 PM   [ Ignore ]   [ # 8 ]  
Summer Student
Total Posts:  12
Joined  12-19-2008

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. 

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!

Profile
 
 
Posted: 28 May 2009 04:55 PM   [ Ignore ]   [ # 9 ]  
Grad Student
Rank
Total Posts:  37
Joined  03-24-2009

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))

Profile
 
 
Posted: 28 May 2009 05:00 PM   [ Ignore ]   [ # 10 ]  
Summer Student
Total Posts:  12
Joined  12-19-2008

True, this is not a valid solution for single file upload; I know it’s not an excuse but I’m only in need of multi-file upload ATM.

Anyone have a solution that will work with single and mutli-file?

Profile
 
 
Posted: 11 August 2009 05:50 PM   [ Ignore ]   [ # 11 ]  
Summer Student
Total Posts:  1
Joined  08-11-2009

fantastic solution, it was what i was looking for! but, there is some new feature that solve the single/multiple upload easier with codeigniter? I say that because seems this post was ended..? raspberry thanks a lot for all!

Profile
 
 
Posted: 11 August 2009 05:52 PM   [ Ignore ]   [ # 12 ]  
Summer Student
Total Posts:  12
Joined  12-19-2008

jviure - I’ve been using two separate libraries for now, Single_upload.php and Upload.php… dirty for sure, but worked in a pinch.

Profile
 
 
Posted: 31 August 2009 06:14 PM   [ Ignore ]   [ # 13 ]  
Grad Student
Rank
Total Posts:  47
Joined  10-16-2008

I’m a little hurry right now because I’m working in a project that is delayed for months because of failures in the project management. I need to use the array-of-files method aforementioned, but as it may be seen, you clearly state:

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.

Which is not the behavior I need for our application. I really need to warn the user if some file couldn’t get to the server ok.

Please, could somebody help me with this issue?. In particular, I’m interested in knowing if somebody has already found a workaround for this, or in either case, what do you suggest me to do in order to save time.

Thanks.

Profile
 
 
Posted: 02 September 2009 01:10 PM   [ Ignore ]   [ # 14 ]  
Grad Student
Rank
Total Posts:  47
Joined  10-16-2008

I’m trying to understand this class in order to implement a partial upload solution (i.e. allow the user to submit several files and individually report the status of each one, with those successfully uploaded through do_upload() as OK and those which not, reporting the errors that the class found); but honestly I can’t figure out what are you trying to do in is_allowed_file_type() with the following code:

foreach ($allowed_types as $val)
        
{
            $mime 
$this->mimes_types(strtolower($val));

            if (
$id === FALSE)
            
{
                $file_temp 
$this->$field->file_temp;
                
$file_type $this->$field->file_type;
            
}
            
else
            
{
                $file_temp 
$this->$field->file_temp[$id];
                
$file_type $this->$field->file_type[$id];
            
}
            
            
// Images get some additional checks
            
if (in_array($val$image_types))
            
{
                
if (getimagesize($file_temp) === FALSE)
                
{
                    
return FALSE;
                
}
            }
                        
// continues... 

This seems to be causing that I can’t upload ZIP files, by example, though I explicitly declared it as an allowed file type. Check this out: If I begin my declaration of allowed file types by ‘jpg|jpeg|zip|...’ and I first upload a ZIP file through an array of files, this code will grab ‘jpg’ as an image type, so in_array($val, $image_types) will return TRUE, and the next thing it will do is to check if the file is an image by calling getimagesize(), but because it is a ZIP file, it will return FALSE. So this ends up by forbidding the ZIP file to be uploaded when it should be not.

Please could you check this code and try to explain me what did you intended to do with it?, I would like to find out if this is a bug in the class.

Thanks.

Profile
 
 
Posted: 06 December 2009 09:18 PM   [ Ignore ]   [ # 15 ]  
Lab Assistant
RankRank
Total Posts:  127
Joined  04-25-2009

thanks for the code.. for me works fine! smile

Profile
 
 
   
1 of 2
1