21

I am trying to get a multiple upload library working for my Codeigniter based website. I have it working almost but I have a slight problem if I upload more than one image, the file extentions get screwed up; for example, if I upload three JPEGS, I get this in my uploads folder,

image1.jpg
image2.jpg.jpg
image3.jpg.jpg.jpg

I cannot see what is causing it, this is the library in question and I am pretty sure that it is in there that the problem is,

<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed'); 

/**
* This library assumes that you have already loaded the default CI Upload Library seperately
* 
* Functions is based upon CI_Upload, Feel free to modify this 
*   library to function as an extension to CI_Upload
* 
* Library modified by: Alvin Mites
* http://www.mitesdesign.com
* 
*/

class Multi_upload  {
    function Multi_upload () {
//      $CI =& get_instance();
    }

    /**
     * Perform multiple file uploads
     * Based upon JQuery Multiple Upload Class
     * see http://www.fyneworks.com/jquery/multiple-file-upload/
     */ 
    function go_upload($field = 'userfile') {
        $CI =& get_instance(); 
        // Is $_FILES[$field] set? If not, no reason to continue.
        if ( ! isset($_FILES[$field]['name'][0]))
        {
            $CI->upload->set_error('upload_no_file_selected');
            return FALSE;
        } else
        {
            $num_files = count($_FILES[$field]['name']) -1;
            $file_list = array();
            $error_hold = array();
            $error_upload = FALSE;
        }

        // Is the upload path valid?
        if ( ! $CI->upload->validate_upload_path())
        {
            // errors will already be set by validate_upload_path() so just return FALSE
            return FALSE;
        }

        for ($i=0; $i < $num_files; $i++) {

//          $fname = $_FILES[$field]['name'][$i];
//          echo "$fname\n\n<br><br>\n\n";

            $error_hold[$i] = FALSE;

            // Was the file able to be uploaded? If not, determine the reason why.
            if ( ! is_uploaded_file($_FILES[$field]['tmp_name'][$i]))
            {
                $error = ( ! isset($_FILES[$field]['error'][$i])) ? 4 : $_FILES[$field]['error'][$i];

                switch($error)
                {
                    case 1:  // UPLOAD_ERR_INI_SIZE
                        $error_hold[$i] = 'upload_file_exceeds_limit';
                        break;
                    case 2: // UPLOAD_ERR_FORM_SIZE
                        $error_hold[$i] = 'upload_file_exceeds_form_limit';
                        break;
                    case 3: // UPLOAD_ERR_PARTIAL
                       $error_hold[$i] = 'upload_file_partial';
                        break;
                    case 4: // UPLOAD_ERR_NO_FILE
                       $error_hold[$i] = 'upload_no_file_selected';
                        break;
                    case 6: // UPLOAD_ERR_NO_TMP_DIR
                        $error_hold[$i] = 'upload_no_temp_directory';
                        break;
                    case 7: // UPLOAD_ERR_CANT_WRITE
                        $error_hold[$i] = 'upload_unable_to_write_file';
                        break;
                    case 8: // UPLOAD_ERR_EXTENSION
                        $error_hold[$i] = 'upload_stopped_by_extension';
                        break;
                    default :
                        $error_hold[$i] = 'upload_no_file_selected';
                        break;
                }

                return FALSE;
            }

            // Set the uploaded data as class variables
            $CI->upload->file_temp = $_FILES[$field]['tmp_name'][$i];        
            $CI->upload->file_name = $CI->upload->_prep_filename($_FILES[$field]['name'][$i]);
            $CI->upload->file_size = $_FILES[$field]['size'][$i];        
            $CI->upload->file_type = preg_replace("/^(.+?);.*$/", "\\1", $_FILES[$field]['type'][$i]);
            $CI->upload->file_type = strtolower($CI->upload->file_type);
            $CI->upload->file_ext  = $CI->upload->get_extension($_FILES[$field]['name'][$i]);

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

            // Is the file type allowed to be uploaded?
            if ( ! $CI->upload->is_allowed_filetype())
            {
                $error_hold[$i] = 'upload_invalid_filetype';
            }

            // Is the file size within the allowed maximum?
            if ( ! $CI->upload->is_allowed_filesize())
            {
                $error_hold[$i] = 'upload_invalid_filesize';
            }

            // Are the image dimensions within the allowed size?
            // Note: This can fail if the server has an open_basdir restriction.
            if ( ! $CI->upload->is_allowed_dimensions())
            {
                $error_hold[$i] = 'upload_invalid_dimensions';
            }

            // Sanitize the file name for security
            $CI->upload->file_name = $CI->upload->clean_file_name($CI->upload->file_name);

            // Remove white spaces in the name
            if ($CI->upload->remove_spaces == TRUE)
            {
                $CI->upload->file_name = preg_replace("/\s+/", "_", $CI->upload->file_name);
            }

            /*
             * Validate the file name
             * This function appends an number onto the end of
             * the file if one with the same name already exists.
             * If it returns false there was a problem.
             */
            $CI->upload->orig_name = $CI->upload->file_name;

            if ($CI->upload->overwrite == FALSE)
            {
                $CI->upload->file_name = $CI->upload->set_filename($CI->upload->upload_path, $CI->upload->file_name);

                if ($CI->upload->file_name === FALSE)
                {
                    $error_hold[$i] = TRUE;
                }
            }

            /*
             * Move the file to the final destination
             * To deal with different server configurations
             * we'll attempt to use copy() first.  If that fails
             * we'll use move_uploaded_file().  One of the two should
             * reliably work in most environments
             */
            if ( ! @copy($CI->upload->file_temp, $CI->upload->upload_path.$CI->upload->file_name))
            {
                if ( ! @move_uploaded_file($CI->upload->file_temp, $CI->upload->upload_path.$CI->upload->file_name))
                {
                     $error_hold[$i] = 'upload_destination_error';
                }
            }

            /*
             * Run the file through the XSS hacking filter
             * This helps prevent malicious code from being
             * embedded within a file.  Scripts can easily
             * be disguised as images or other file types.
             */
            if ($CI->upload->xss_clean == TRUE)
            {
                $CI->upload->do_xss_clean();
            }

            if ($error_hold[$i]) {
                $error_upload = TRUE;

//                echo $error_hold[$i];
            } else {
                if ($imageVar = $this->multiple_image_properties($CI->upload->upload_path.$CI->upload->file_name)) {

                    $file_list[] = array(
                            'name' => $CI->upload->file_name,
                            'file' => $CI->upload->upload_path.$CI->upload->file_name,
                            'size' => $CI->upload->file_size,
                            'ext' => $CI->upload->file_ext,
                            'image_type' => $imageVar->image_type,
                            'height' => $imageVar->height,
                            'width' => $imageVar->width
                            );
                } else {
                    $file_list[] = array(
                            'name' => $CI->upload->file_name,
                            'file' => $CI->upload->upload_path.$CI->upload->file_name,
                            'size' => $CI->upload->file_size,
                            'type' => $CI->upload->file_type,
                            'ext' => $CI->upload->file_ext,
                            );
                }
            }

// For debugging
/*            
            if (strlen($error_hold[$i]) > 1) {
                    print_r($error_hold);
            }
*/            
        } // end for loop

        // Add error display for individual files        
        if ($error_upload) {
            $this->set_error($error_hold);
            return FALSE;
        } else {
            return $file_list;
        }    
    }

    // --------------------------------------------------------------------

    /**
     * Set Image Properties
     *
     * Uses GD to determine the width/height/type of image
     *
     * @access    public
     * @param    string
     * @return    void
     */    
    function multiple_image_properties($path = '')
    {
        $CI =& get_instance(); 
        if ( ! $CI->upload->is_image())
        {
            return false;
        }

        if (function_exists('getimagesize'))
        {
            if (FALSE !== ($D = @getimagesize($path)))
            {    
                $types = array(1 => 'gif', 2 => 'jpeg', 3 => 'png');

                $image->width       = $D['0'];
                $image->height      = $D['1'];
                $image->image_type        = ( ! isset($types[$D['2']])) ? 'unknown' : $types[$D['2']];

                return $image;
            }
        }
    }

    // --------------------------------------------------------------------

    /**
     * Set an error message
     *
     * @access    public
     * @param    string
     * @return    void
     */    
    function set_error($msg)
    {
        $CI =& get_instance();    
        $CI->lang->load('upload');

        if (is_array($msg))
        {
            foreach ($msg as $val)
            {
                $msg = ($CI->lang->line($val) == FALSE) ? $val : $CI->lang->line($val);                
                $this->error_msg[] = $msg;
                log_message('error', $msg);
            }        
        }
        else
        {
            $msg = ($CI->lang->line($msg) == FALSE) ? $msg : $CI->lang->line($msg);
            $this->error_msg[] = $msg;
            log_message('error', $msg);
        }
    }

    // --------------------------------------------------------------------
}
?>

5 Answers 5

17

Faced the exact similar stuff 2 days ago but did it the old fashioned way hope it helps. try this ..

function tester(){

 $this->load->library('upload');  // NOTE: always load the library outside the loop
 $this->total_count_of_files = count($_FILES['filename']['name'])
 /*Because here we are adding the "$_FILES['userfile']['name']" which increases the count, and for next loop it raises an exception, And also If we have different types of fileuploads */
 for($i=0; $i<$this->total_count_of_files; $i++)
 {

   $_FILES['userfile']['name']    = $_FILES['filename']['name'][$i];
   $_FILES['userfile']['type']    = $_FILES['filename']['type'][$i];
   $_FILES['userfile']['tmp_name'] = $_FILES['filename']['tmp_name'][$i];
   $_FILES['userfile']['error']       = $_FILES['filename']['error'][$i];
   $_FILES['userfile']['size']    = $_FILES['filename']['size'][$i];

   $config['file_name']     = 'test_'.$i;
   $config['upload_path']   = './public/uploads/';
   $config['allowed_types'] = 'jpg|jpeg|gif|png';
   $config['max_size']      = '0';
   $config['overwrite']     = FALSE;

  $this->upload->initialize($config);

  if($this->upload->do_upload())
  {
    $error += 0;
  }else{
    $error += 1;
  }
 }

 if($error > 0){ return FALSE; }else{ return TRUE; }

}
Sign up to request clarification or add additional context in comments.

5 Comments

this had been giving me a headache all morning, I modded your version for myself and it works great!
This is pretty good. There are some syntax errors, but with a bit of tweaking it works. replace foreach with for. replace $j with $i
@JannieT It counts the number of error messages, then at the end if the number of errors are 0 then true is returned, otherwise false is returned.
@Daniel ummm I was suggesting the code be simplified to if(!$this->upload->do_upload()) { $error += 1; } without the else
@JannieT Yeah I see what you mean, depends on your coding style :)
8

I solved this exact problem by amending the Upload.php files located in the library folder.

Comment out line 935:

$filename = $this->file_name;

Comments

5

For me it was enough to recall $this->upload->initialize($config); every time I called $this->upload->do_upload()

1 Comment

This worked for me. For some reason it was retaining the config data from the previous call to do_upload. Calling initialize() forces it to update the config data.
1

I am a bit confused by your answer thephpx. Won't restructuring $_FILES like that kill off the subarrays once you ahve run it once?

At any rate, I was trying OP's approach by adding the extra index to the a few of the upload library's lines.

I made it work by putting the for loop (over all files) in the upload controller, and the extra index $k as a parameter in the do_upload function in the library.

            $this->load->library('upload');
        for ($k = 0; $k < count($_FILES['userfile']['name']); $k++) {
            $this->upload->initialize($upload); //must reinitialize to get rid of your bug ( i had it as well)
            if (!$this->upload->do_upload('userfile',$k)) {
                $this->load->view('upload/image_form', $data + array('error'=>$this->upload->display_errors()));
            }
            $udata[$k] = $this->upload->data(); //gradually build up upload->data()
        }

1 Comment

"Won't restructuring $_FILES like that kill off the subarrays once you ahve run it once?" No. He is only modifying the $_FILES['userfile'] array (not his initial $_FILES['filename'] array. As the do_upload() is being run inside the loop, the $_FILES['userfile'] array being rest every time doesn't matter.
0

I was able to get multiple file uploads to work with clux's method but I had to modify the upload class slightly (I'm using Codeigniter 2). First I created a duplicate of the CI upload class into my applications library.

Line 143:

public function do_upload($field = 'userfile')

change to

public function do_upload($field = 'userfile', $i = 0)

And between lines 160 and 200, you must add [$i] to the end of the $_FILES variables.

Example:

is_uploaded_file($_FILES[$field]['tmp_name'])

change to:

is_uploaded_file($_FILES[$field]['tmp_name'][$i])

I believe there is a total of 9 of them.

1 Comment

This will cause problems when you upload a single file.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.