Welcome Guest, Not a member yet? Register   Sign In
Using SWFUpload + Sessions + upload class, how I did it.
#1

[eluser]~Chris~[/eluser]
Newer Version HERE! http://ellislab.com/forums/viewthread/221152/

Hello everyone. I have been a member for some time, and I have used the forums many times to solve many a problem, but I haven't really contributed much. I usually just find my solution and move on.
SwfUploader is something I have been playing around with for a while now, but never did find a solid implementation to keep the sessions when I uploaded files. Well I finally figured out a solution that fits me, and I think works very well. I thought I would post about it and maybe help someone else out, considering this has been a fustrating topic for many. So here is my implementation:

Let me start out by saying that you must be using the native session library. It can be found in the wiki. By allowing your sessions to be handled by php, you can pick up the session in from the "flash" useragent.

I modified the native session library. I figured it was ok, considering by using the native session library, I am still not changing the core code.

First of all, to use the swfUploader with the code igniter upload class, you need to add the appropriate mime types.

/system/application/config/mimes.php
Code:
'jpeg'    =>    array('image/jpeg', 'image/pjpeg', 'application/octet-stream'),
'jpg'    =>    array('image/jpeg', 'image/pjpeg', 'application/octet-stream'),
'jpe'    =>    array('image/jpeg', 'image/pjpeg', 'application/octet-stream'),
For every file type that you need to be able to upload with swfuploader, you need to add the 'application/octet-stream' mime type to the file extesion in mimes.php. Here, I added the mime type to jpeg, jpg, and jpe. This is just because it is how swfupload uploads the data.

Next you need to modify the native sessions library
what we will do is enable a paramater for the session id, and if the session id is set, then we will tell the php session to use that session id, instead of trying to create a new one for the new useragent when flash accesses the upload script.

/system/application/libraries/Session.php (roughly line 31)
Code:
//Add $params = array() as a parameter
//so if theres no entry (like the default way of calling it) it will just default
//to an array
function CI_Session($params = array())
{
    $this->object =& get_instance();
    log_message('debug', "Native_session Class Initialized");

    //were looking for $params['session_id']. if its set, then we want to
    //start the session with that session id. we need to pass it to the function
    //that starts the session.
    if(isset($params['session_id'])){
        log_message("debug", "Session ID is passed, using ".$params['session_id']);
            $this->_sess_run($params['session_id']);
    } else {
        //and if its not set, well start the sessions to classic way.
            log_message("debug", "Figuring Out Session ID automagically");
            $this->_sess_run();
        }
}
I placed all of my edits in the comments. Basically, i just added a parameter, and if that parameter is set, I pass it to the the method that actually starts the session, so we will need to edit that method as well, in the same file. Also note, I sprinkled in some "log_messages" this can be handy as you wont be able to see output of the upload script used by swfuploader. so you can watch the logs if you enable them, to debug your script.

/system/application/libraries/Session.php (roughly line 146)
Code:
//again, here, I add a parameter $phpsessid and give it a default of null, so it is reverse
//compatible
function _sess_run($phpsessid = null)
    {
        //if the paramater is NOT null (something was passed to it)
            //then we will tell php to use the session id that was passed
            if ($phpsessid != null){
           log_message("debug", "setting session id to use: ".$phpsessid);
           //this is where the magic happens
               session_id($phpsessid);
        }
        session_start();

        $session_id_ttl = $this->object->config->item('sess_expiration');
...
Here, as you see, (i added comments to what I changed) I added a paramater to the method.
if the paramater is set (it should be a session id) then we tell php to start the session using that session id.

Now you can use the current session data with swf upload while using the upload class, which I will also demonstrate.

The Controller (/system/application/controllers/fileupload.php
Code:
class Fileupload extends Controller {

    function Fileupload()
    {
    parent::Controller();
    }

    function index(){
        //load helpers
        $this->load->helper(array('url', 'form'));
        //load session library the normal way
        $this->load->library('session');

        $this->load->view('uploadform');
    }

    function upload(){
       //you should have swfuploader POST your session id (youll see in the view)
       $params['session_id'] = $this->input->post("PHPSESSID");
       //load the session library the new way, by passing it the session id
       $this->load->library('session', $params);
       $this->load->library('upload') // load the upload class

       //now if the session was posted, and it loaded correctly, you will have
       //access to your session !
       if ($this->session->userdata('logged_in') != true) show_404(); //cancel if the user is not logged in

        $user_id = $this->session->userdata('user_id');

        $config['upload_path'] = $_SERVER['DOCUMENT_ROOT'].'/assets/uploads/';
        //make sure this directory exists and is writeable!
        $config['allowed_types'] = 'jpg';
        $config['max_size']    = '10240';
        
        if ( ! $this->upload->do_upload("Filedata")){
             //upload failed, do stuff
             show_404(); //maybe? you can handle it how you want with swfuploader
        } else {
             //insert stuff to a database.
        }
    }
}
#2

[eluser]~Chris~[/eluser]
the view (/system/application/views/uploadform.php)
Code:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
&lt;html &gt;

&lt;head&gt;
    &lt;meta http-equiv="content-type" content="text/html; charset=iso-8859-1" /&gt;
    &lt;title&gt;Upload Test&lt;/title&gt;
    &lt;link href="/assets/css/default.css" rel="stylesheet" type="text/css" /&gt;
    &lt;script type="text/javascript" src="/assets/js/swfupload.js"&gt;&lt;/script&gt;
    &lt;script type="text/javascript" src="/assets/js/swfupload.queue.js"&gt;&lt;/script&gt;
    &lt;script type="text/javascript" src="/assets/js/fileprogress.js"&gt;&lt;/script&gt;
    &lt;script type="text/javascript" src="/assets/js/handlers.js"&gt;&lt;/script&gt;
&lt;/head&gt;
&lt;body&gt;

&lt;script type="text/javascript"&gt;

        var swfu;

        window.onload = function() {
            var settings = {
                
                                flash_url : "&lt;?=site_url()?&gt;/assets/flash/swfupload_f9.swf",
                //points the our codeigniter method
                                upload_url: "&lt;?=site_url()?&gt;/fileupload/upload",
                                //make sure to pass our session id (assuming there is a logged in user)
                post_params: {"PHPSESSID" : "&lt;?=$this->session->userdata('session_id')?&gt;"},
                file_size_limit : "10 MB",
                file_types : "*.jpg",
                file_types_description : "Images",
                file_upload_limit : 100,
                file_queue_limit : 0,
                custom_settings : {
                    progressTarget : "fsUploadProgress",
                    cancelButtonId : "btnCancel"
                },
                debug: false,

                // The event handler functions are defined in handlers.js
                file_queued_handler : fileQueued,
                file_queue_error_handler : fileQueueError,
                file_dialog_complete_handler : fileDialogComplete,
                upload_start_handler : uploadStart,
                upload_progress_handler : uploadProgress,
                upload_error_handler : uploadError,
                upload_success_handler : uploadSuccess,
                upload_complete_handler : uploadComplete,
                queue_complete_handler : queueComplete    // Queue plugin event
            };

            swfu = new SWFUpload(settings);
         };
&lt;/script&gt;
&lt;form id="form1" action="" method="post" enctype="multipart/form-data"&gt;
    
    <div class="fieldset flash" id="fsUploadProgress">
        <span class="legend">Upload Queue</span>
    </div>
    <div id="divStatus">0 Files Uploaded</div>
    <div>
        
         &lt;input type="button" value="Select Files" onclick="swfu.selectFiles()" style="font-size: 8pt;" /&gt;
         &lt;input id="btnCancel" type="button" value="Cancel All Uploads" onclick="swfu.cancelQueue();" disabled="disabled" style="font-size: 8pt;" /&gt;


    </div>
&lt;/form&gt;
&lt;/body&gt;
&lt;/html&gt;
Notice in the javascript, I passed along the session id to the swfuploader, and told it to call our very own code igniter method.

All the included files would be the demonstration files that you can download with swfuploader.

Now, my personal code looks much different, so i stripped a lot out and made it basic. I havent tested this exact code, so you may need to debug it. It is just examples anway.

in the sessions class, you could even tell it to automatically load the session id if its posted, then you could autoload the sessions class, instead of having to call it.

Anyway, there it is. Hope it helps.
#3

[eluser]omed habib[/eluser]
Chris,

First off, this was an absolutely and positively amazing job. Thank you!!!

Second, it should be worth noting that:

1. The session library CANNOT be autoloaded in the config/autoload.php file for this to work (or anywhere else for that matter, CI will just ignore the second attempt)
2. In the controller Fileupload::upload() , you need to set the upload config parameters BEFORE you load the upload library...
3. ... and then when you do load the upload library, you need to pass those configs as an argument:

Code:
// Set upload path
$config['upload_path'] = '/uploads';
$config['allowed_types'] = 'jpg';
$config['max_size']    = '10240';

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

Other than that... I can attest that this method also works for the latest version of SWFUpload v.2.2.0 Beta 3 release. However, I ignored everything in the view file except for the post params:

Code:
post_params: {"PHPSESSID" : "&lt;?=$this->session->userdata('session_id')?&gt;"},

Thank you for your contribution!!
#4

[eluser]~Chris~[/eluser]
Late Response, right?
LOL.
I wasn't clear in what I said. What I meant was: You could actually modify the script a little bit, if you wanted, in order to use it with autoload.
Simply by checking if PHPSESSID exists in the POST array, and using it if it does in the sessions library. And it could continue on to start up sessions normally if there was no phpsessid in the post array.

haha, and yes, the parameters need to go before you load the library. My mistake. I must have zoned when I wrote that part.
#5

[eluser]Jupiter[/eluser]
One important remark: when using SWFUpload from a Mac, it appends the port :80 to your upload URL. Be sure to sanitize this in case you pull it from $_SERVER['HTTP_HOST'] and do someting with it in your script.
#6

[eluser]CollinsSolutions[/eluser]
i am trying this same implementation but instead of uploading i am uploading to a database. Its not working for me. Here is my code

Code:
//you should have swfuploader POST your session id (youll see in the view)
    $params['session_id'] = $this->input->post("PHPSESSID");
    $this->load->library('session', $params);
    
        
    $upload_name = 'Filedata';
    print_r($_FILES);
    $count = 0;
    $count = count($_FILES[$upload_name]['size']);
    //echo $count;
    for($i = 1; $i <= $count-1; $i++):
        $fileName = $_FILES[$upload_name]['name'][$i];
        //echo 'Name is: ' . $fileName . '<BR>';
        $file = array(
        'name' => addslashes($fileName),
        'type' => $_FILES[$upload_name]['type'][$i],
        'size' => $_FILES[$upload_name]['size'][$i],
        'user_id' => $this->dx_auth->get_user_id());
        $tmpName  = $_FILES[$upload_name]['tmp_name'][$i];
        $content = read_file($tmpName);
        $content = addslashes($content);
        $file['content'] = $content;
        $this->db->insert('files', $file);
    endfor;
                

        $data['user_id'] = $this->dx_auth->get_user_id();
        $data['profile'] = $this->user_profile->get_profile($data['user_id']);
        $data['url'] = base_url();
        $data['site_url'] = site_url();
        $data['query'] = $this->db->get('portfolionames');
        $data['links'] = $this->db->query('SELECT * FROM links ORDER BY sort_order');
        $data['ownedfiles'] = $this->db->query('SELECT * FROM files WHERE user_id = ' . $this->dx_auth->get_user_id());
        $this->load->view('manage_view',$data);

Any ideas?
#7

[eluser]pistolPete[/eluser]
[quote author="CollinsSolutions" date="1236903951"]Its not working for me[/quote]

Give a better error description.
Are you using native PHP sessions?
What's your database layout?
...
#8

[eluser]CollinsSolutions[/eluser]
i think its native sessions. Database layout inst the problem. That i had working with standard uploader, its the SWF that's not working. Since its flash its hard to debug since there is no redirecting to the page to output anything.
#9

[eluser]pistolPete[/eluser]
Use the debug setting of SWFupload:
http://demo.swfupload.org/Documentation/
Code:
(...)
debug : true,
(...)

Additionally use Firebug: http://www.getfirebug.com
#10

[eluser]CollinsSolutions[/eluser]
that helped it looks like its uploading fine i am just not picking it up to post it to the database in php. Is there a way to write to that log from my upload function?




Theme © iAndrew 2016 - Forum software by © MyBB