0

I am trying to implement a multiple file upload script to codeigniter. the script can be find here http://valums.com/ajax-upload/. I find it quite good, so I decide to put in current apps.

The problem is, I couldn't access the uploaded files with codeigniter. If you a codeigniter developer please advise how I could grap the file send by the script ?

2
  • And rurunforest, you should add more info. Commented Jan 3, 2011 at 16:11
  • @Ipalaus Thanks , I didn't know I should do that, just ticked the Vs Commented Jan 9, 2011 at 17:36

4 Answers 4

1

CodeIgniter has a few ways to handle uploads, but since your ajax-upload script already has a handler, you should use that.

How to:

Create a new file in your application/libraries folder, named Qqfileuploader.php and paste this in it:

<?php if (!defined('BASEPATH')) exit('No direct script access allowed');
    class Qqfileuploader {
        private $allowedExtensions = array();
        private $sizeLimit = 10485760;
        private $file;

        function __construct(array $allowedExtensions = array(), $sizeLimit = 10485760){        
            $allowedExtensions = array_map("strtolower", $allowedExtensions);

            $this->allowedExtensions = $allowedExtensions;        
            $this->sizeLimit = $sizeLimit;

            $this->checkServerSettings();       

            if (isset($_GET['qqfile'])) {
                $this->file = new qqUploadedFileXhr();
            } elseif (isset($_FILES['qqfile'])) {
                $this->file = new qqUploadedFileForm();
            } else {
                $this->file = false; 
            }
        }

        private function checkServerSettings(){        
            $postSize = $this->toBytes(ini_get('post_max_size'));
            $uploadSize = $this->toBytes(ini_get('upload_max_filesize'));        

            if ($postSize < $this->sizeLimit || $uploadSize < $this->sizeLimit){
                $size = max(1, $this->sizeLimit / 1024 / 1024) . 'M';             
                die("{'error':'increase post_max_size and upload_max_filesize to $size'}");    
            }        
        }

        private function toBytes($str){
            $val = trim($str);
            $last = strtolower($str[strlen($str)-1]);
            switch($last) {
                case 'g': $val *= 1024;
                case 'm': $val *= 1024;
                case 'k': $val *= 1024;        
            }
            return $val;
        }

        /**
         * Returns array('success'=>true) or array('error'=>'error message')
         */
        function handleUpload($uploadDirectory, $replaceOldFile = FALSE){
            if (!is_writable($uploadDirectory)){
                return array('error' => "Server error. Upload directory isn't writable.");
            }

            if (!$this->file){
                return array('error' => 'No files were uploaded.');
            }

            $size = $this->file->getSize();

            if ($size == 0) {
                return array('error' => 'File is empty');
            }

            if ($size > $this->sizeLimit) {
                return array('error' => 'File is too large');
            }

            $pathinfo = pathinfo($this->file->getName());
            $filename = $pathinfo['filename'];
            //$filename = md5(uniqid());
            $ext = $pathinfo['extension'];

            if($this->allowedExtensions && !in_array(strtolower($ext), $this->allowedExtensions)){
                $these = implode(', ', $this->allowedExtensions);
                return array('error' => 'File has an invalid extension, it should be one of '. $these . '.');
            }

            if(!$replaceOldFile){
                /// don't overwrite previous files that were uploaded
                while (file_exists($uploadDirectory . $filename . '.' . $ext)) {
                    $filename .= rand(10, 99);
                }
            }

            if ($this->file->save($uploadDirectory . $filename . '.' . $ext)){
                return array('success'=>true);
            } else {
                return array('error'=> 'Could not save uploaded file.' .
                    'The upload was cancelled, or server error encountered');
            }

        }    
    }

Now, in the controller that you're uploading to, do this:

// list of valid extensions, ex. array("jpeg", "xml", "bmp")
$allowedExtensions = array();
// max file size in bytes
$sizeLimit = 10 * 1024 * 1024;

$this->load->library("Qqfileuploader",array($allowedExtensions, $sizeLimit));
$this->Qqfileuploader->handleUpload('uploads/');
// to pass data through iframe you will need to encode all html tags
echo htmlspecialchars(json_encode($result), ENT_NOQUOTES);

That should work.

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

Comments

1

Actually CodeIgniter libraries seem to allow only 1 parameter to be passed to constructor. So the Adrian Gonzales's code didn't quite work for me - I had to change the constructor to accept the parameters as a single array (as noted here: http://codeigniter.com/user_guide/general/creating_libraries.html). And then it worked.

Here is my library code:

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


class qqFileUploader {
    private $allowedExtensions = array();
    private $sizeLimit = 10485760;
    private $file;

    function __construct($params = array()){
        $allowedExtensions = $params['allowedExtensions'];
        $sizeLimit = $params['sizeLimit'];

        $allowedExtensions = array_map("strtolower", $allowedExtensions);

        $this->allowedExtensions = $allowedExtensions;        
        $this->sizeLimit = $sizeLimit;

        $this->checkServerSettings();       

        if (isset($_GET['qqfile'])) {
            $this->file = new qqUploadedFileXhr();
        } elseif (isset($_FILES['qqfile'])) {
            $this->file = new qqUploadedFileForm();
        } else {
            $this->file = false; 
        }
    }

    private function checkServerSettings(){        
        $postSize = $this->toBytes(ini_get('post_max_size'));
        $uploadSize = $this->toBytes(ini_get('upload_max_filesize'));        

        if ($postSize < $this->sizeLimit || $uploadSize < $this->sizeLimit){
            $size = max(1, $this->sizeLimit / 1024 / 1024) . 'M';             

            die("{'error':'increase post_max_size and upload_max_filesize to $size'}");    
        }        
    }

    private function toBytes($str){
        $val = trim($str);
        $last = strtolower($str[strlen($str)-1]);
        switch($last) {
            case 'g': $val *= 1024;
            case 'm': $val *= 1024;
            case 'k': $val *= 1024;        
        }
        return $val;
    }


    function handleUpload($uploadDirectory, $replaceOldFile = FALSE){
        if (!is_writable($uploadDirectory)){
            return array('error' => "Server error. Upload directory isn't writable.");
        }

        if (!$this->file){
            return array('error' => 'No files were uploaded.');
        }

        $size = $this->file->getSize();

        if ($size == 0) {
            return array('error' => 'File is empty');
        }

        if ($size > $this->sizeLimit) {
            return array('error' => 'File is too large');
        }

        $pathinfo = pathinfo($this->file->getName());
        //$filename = $pathinfo['filename'];
        $filename = md5(uniqid());
        $ext = $pathinfo['extension'];

        if($this->allowedExtensions && !in_array(strtolower($ext), $this->allowedExtensions)){
            $these = implode(', ', $this->allowedExtensions);
            return array('error' => 'File has an invalid extension, it should be one of '. $these . '.');
        }

        if(!$replaceOldFile){
            /// don't overwrite previous files that were uploaded
            while (file_exists($uploadDirectory . $filename . '.' . $ext)) {
                $filename .= rand(10, 99);
            }
        }

        if ($this->file->save($uploadDirectory . $filename . '.' . $ext)){
            return array('success'=>true, 'fileName' => $filename . '.' . $ext);
        } else {
            return array('error'=> 'Could not save uploaded file.' .
                'The upload was cancelled, or server error encountered');
        }

    }    
}


class qqUploadedFileXhr {

    function save($path) {    
        $input = fopen("php://input", "r");
        $temp = tmpfile();
        $realSize = stream_copy_to_stream($input, $temp);
        fclose($input);

        if ($realSize != $this->getSize()){            
            return false;
        }

        $target = fopen($path, "w");        
        fseek($temp, 0, SEEK_SET);
        stream_copy_to_stream($temp, $target);
        fclose($target);

        return true;
    }
    function getName() {
        return $_GET['qqfile'];
    }
    function getSize() {
        if (isset($_SERVER["CONTENT_LENGTH"])){
            return (int)$_SERVER["CONTENT_LENGTH"];            
        } else {
            throw new Exception('Getting content length is not supported.');
        }      
    }   
}


class qqUploadedFileForm {  
    /**
     * Save the file to the specified path
     * @return boolean TRUE on success
     */
    function save($path) {
        if(!move_uploaded_file($_FILES['qqfile']['tmp_name'], $path)){
            return false;
        }
        return true;
    }
    function getName() {
        return $_FILES['qqfile']['name'];
    }
    function getSize() {
        return $_FILES['qqfile']['size'];
    }
}

2 Comments

How did you add qqUploadedFileXhr() and qqUploadedFileForm() classes in the same library ?
Thanks you so much. I did it by separating each classes in separate library file Lolzz
0

Take a lot to the /server/php.php file: https://github.com/valums/file-uploader/blob/master/server/php.php

You've to reproduce something like that on your controller to handle the XMLHttpRequest of the ajax script.

Comments

0

I find a very easy solution.

First, go to the script, edit the querystring variable, so that i will produce segmented uri.

Then In the controller, I use file_get_contents("php://input") to grab the content. To get the name of the file just do $this->input->uri(3);

Comments

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.