2009-12-15 34 views
20

Tôi đang cố gắng để có được một thư viện tải lên nhiều làm việc cho trang web dựa trên Codeigniter của tôi. Tôi có nó làm việc gần như nhưng tôi có một vấn đề nhỏ nếu tôi tải lên nhiều hơn một hình ảnh, các tập tin mở rộng nhận được hơi say lên; ví dụ, nếu tôi tải lên ba hình ảnh JPEG, tôi có được điều này trong thư mục upload của tôi,Codeigniter nhiều tập tin tải lên messes mở rộng tập tin

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

Tôi không thể nhìn thấy những gì đang gây ra nó, đây là thư viện trong câu hỏi và tôi khá chắc chắn rằng nó là ở đó mà vấn đề là,

<?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); 
     } 
    } 

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

Trả lời

7

Tôi đã giải quyết vấn đề chính xác này bằng cách sửa đổi tệp Upload.php nằm trong thư mục thư viện.

Comment ra dòng 935:

$filename = $this->file_name; 
17

Đối mặt với nội dung tương tự chính xác 2 ngày trước nhưng đã làm theo cách cũ, hy vọng điều đó sẽ hữu ích. hãy thử điều này ..

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; } 

} 
+2

điều này đã khiến tôi đau đầu vào buổi sáng, tôi đã sửa đổi phiên bản của bạn cho chính tôi và nó hoạt động tuyệt vời! –

+1

Điều này khá tốt. Có một số lỗi cú pháp, nhưng với một chút tinh chỉnh nó hoạt động. thay thế foreach bằng cho. thay thế $ j bằng $ i – k00k

+0

Có, câu trả lời hữu ích. Chỉ cần không chắc chắn những gì $ lỗi + = 0 không. –

1

Tôi hơi bối rối bởi câu trả lời của bạn thephpx. Sẽ không tái cơ cấu $ _FILES như vậy giết chết các subarrays một khi bạn ahve chạy nó một lần?

Ở mức nào, tôi đã thử phương pháp tiếp cận của OP bằng cách thêm chỉ mục bổ sung vào một vài dòng của thư viện tải lên.

Tôi đã làm cho nó hoạt động bằng cách đặt vòng lặp for (trên tất cả các tệp) trong bộ điều khiển tải lên và chỉ mục bổ sung $ k làm tham số trong hàm do_upload trong thư viện.

  $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() 
     } 
+0

"Sẽ không tái cơ cấu $ _FILES như vậy sẽ loại bỏ các subrays một khi bạn ahve chạy nó một lần?" Không. Anh ta chỉ sửa đổi mảng $ _FILES ['userfile'] (không phải mảng $ _FILES ['filename'] ban đầu của mình. Do do_upload() đang được chạy bên trong vòng lặp, $ _FILES ['userfile'] mảng được nghỉ ngơi mỗi lần không quan trọng –

3

Đối với tôi đó là đủ để nhớ lại $this->upload->initialize($config); mỗi khi tôi gọi $this->upload->do_upload()

+0

Điều này làm việc cho tôi.Vì một số lý do nó đã giữ lại dữ liệu cấu hình từ cuộc gọi trước đó đến do_upload.Chú ý khởi tạo() buộc nó cập nhật dữ liệu cấu hình – DonutReply

+0

Nó hoạt động nhờ –

0

tôi đã có thể để có được nhiều tập tin tải lên để làm việc với phương pháp Clux nhưng tôi đã phải sửa đổi lớp tải lên một chút (Tôi đang sử dụng Codeigniter 2). Đầu tiên tôi tạo một bản sao của lớp tải lên CI vào thư viện ứng dụng của tôi.

Dòng 143:

public function do_upload($field = 'userfile') 

thay đổi

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

Và giữa các dòng 160 và 200, bạn phải thêm [$ i] để kết thúc _FILES biến $.

Ví dụ:

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

thay đổi:

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

Tôi tin rằng có tổng cộng 9 trong số họ.

+0

sẽ gây ra sự cố khi bạn tải lên một tệp. – Pjottur

Các vấn đề liên quan