[EXTENSION] FancyUpload

Hello,

I’am implementint this extension but I get this error with the multiupload:


Upload failed: Server returned HTTP-Status #302

The firebug (firefox’s addons) show this:


document.search is not a function

el = document.search('.file-success'); 

That is from this function:


onComplete:function() {

               // document.id('fancy-status').setStyle('display','none');

               //up.remove();

               el = document.search('.file-success');

               for (i=0; i<el.length; i++){

                   el[i].destroy();

               }

            },

                        });



With the simple upload I get this error:


Please try again. (Error: #403 httpStatus)

What’s the problem? Can you help me?

Sure, I’ll do my best to help you…could you please provide more information on:

  • the Yii version you’re using

  • the view source code that contains the widget

  • the controller/action source code that is called in the url parameter of the widget

the document.search function is an alternative way of coding in mootools that avoid conflicts with jQuery, because the default way of accessing elements in mootools is also $(‘id’), exactly as in jQuery. If the function is not found, please, check if all javascripts were loaded into your page

Meanwhile, from the FanyUpload website, I got the following that might be useful for us to start solving the 302 problem:

"…Do you use an absolute url? 302 usually shows that there is something wrong with the url. Do you return a response from the server? Do you try to detect a flash request or use the same upload code for all uploads?.."

"…Jeez ! I think I realized what’s the problem!

302 is a page moved or a redirection.

The Uploader file is hosted in a folder that requires authentication.

When the flash uploader sends an unauthenticated request to that file, the server redirects to somewhere else (login page).

Thus, the flash uploader never reaches the right upload file and keeps borking an httpStatus 302…"

Please, perform a test changing your controller/action upload to simply:

echo "reached";

Then try to access it directly like

http://yourhost/yourcontroller/uploadaction and see if it returns the text correctly

and let us know what happens…

ps.: the 403 error seems to be happening in Yii 1.1 only…unfortunatelly, I haven’t had time to go deeply in this case yet

Regards

:)

Hey Scoob.

I’ve got it. I know why I get Error 400 in my project.

It is because I have enabled the Csrf Validation. If I set it to false, the upload works.

I haven’t fixed it yet, but I believe that I can use the data array to pass the Csrf Validation token.

I’ll let you know.

Well, it didn’t work.

I added this:




'data'=>array('YII_CSRF_TOKEN'=>Yii::app()->request->csrfToken)



But I still get Error 400.

Any ideas? I really don’t want to disable Csrf Validation.

Thanks!

Very good, man!! Congratulations for discovering that! Lets start some tests so?

I’ve searched around the net and Yii forum (http://www.yiiframework.com/forum/index.php?/topic/5362-swfupload-и-csrf-validation/page__hl__csrf%20__fromsearch__1) and the problem seems to be related to PHP session, so, please, put this little piece of code in your controller/upload action, before your existing code, at the beginning, like




public function actionUpload(){

  $logFile = Yii::app()->getBasePath().'/tmp/log.txt';  //be sure to adjust this path


   $result = array();

   if(count($_GET))   { $result[get] = $_GET; }

   if(count($_POST))  { $result[post] = $_POST; }

   if(count($_FILES)) { $result[files] = $_FILES; }


   //lets compare if $_POST['PHPSESSID'] really contains the session Id dumped in the lines above

   $result[mySessionId] = $_POST['PHPSESSID'];


   //here, starts the session with the same Id

   session_id($_POST['PHPSESSID']);

   session_start();


   //lets log so

   $log = @fopen($logFile, 'a');

   if ($log) {

      fputs($log, print_r($result, true) . "\n---\n");

      fclose($log);

   }


   //load the file and do whatever you need beyond this point

   $file = CUploadedFile::getInstanceByName("Filedata");

...

...

...



What it does, as you can see, is to log everything comming from the view. So then start the session with the same PHPSESSID sent by the widget via appendCookieData option, that you should add to your parameters as follows:




'data'=>array('YII_CSRF_TOKEN'=>Yii::app()->request->csrfToken),    //send your csrf token

'appendCookieData'=>true,  //this will send PHPSESSID automatically



Please, let me know what happens.

regards!!!

:)

Well, it is working beautifly now. These two snippets made it all work.

Thank you very much Scoob, I really appreciate your help.

Developers such as yourself are a reason why I stay with Yii Framework.

Hi scoob.junior

ok, here you are:

  • Version: 1.0.11.r1579

View source:

The same code of the Yii extension page of sfancyupload:

I have the below code in this file: /protected/views/curriculum/fancyUploader.php




<?php

//------------- for multiple file upload (queue) --------------

$statusBoxId  = 'fancy-status';

$clearButton  = 'fancy-clear';

$uploadButton = 'fancy-upload';


$this->widget('application.extensions.fancyupload.SFancyQueue',

    array(

        'name'=>'form-fancy',

        'statusBoxId'=>$statusBoxId,            //id for the container div

        'clearButton'=>$clearButton,            //id for "Clear List" link

        'uploadButton'=>$uploadButton,          //id for "Start Upload" link

        'clearButtonLabel'=>'Limpar Lista',     //label for "Clear List" link

        'uploadButtonLabel'=>'Iniciar Carga',    //label for "Start Upload" link

        'targetLabel'=>'Seleccionar Archivos',          //label for "select files" link

        'options'=> array(

                'verbose'=>true,  //remove in production

                'url'=>$this->createUrl('curriculum/UploadedFiles'),          //send files to this controller/action

                'multiple'=>true,                                       //multiple files

                'target'=>'fancy-browse',                               //id for "select files" link

                'typeFilter'=>array('Images (jpg, jpeg, gif, png)'=>'*.jpg; *.jpeg; *.gif; *.png','Compressed (zip, rar)'=>'*.zip; *.rar'),   //accept only images and compressed files (better check the mimetype in the controller which receives the file)

                'instantStart'=>false,                                  //do not upload right after the selection of files

                'data'=>array(//'YII_CSRF_TOKEN'=>Yii::app()->request->csrfToken),    //send your csrf token

                              //'appendCookieData'=>true,

                              'extradata'=>'your_additional_content'),  //accessible in the controller via $_POST['extradata'] or $_POST['whatever_you_put_in_the_key']

            ),




        'callbacks' => array(

            //'onComplete' => 'function(){alert("Complete");}',

            //'onCancel' => 'function(evt,queueId,fileObj,data){alert("Cancelled");}',


            'onLoad'=>"function() {

                    document.id('$statusBoxId').removeClass('hide');

                    document.id('fancy-fallback').destroy();


                    // We relay the interactions with the overlayed flash to the link

                    this.target.addEvents({

                            click: function() {

                                    return false;

                            },

                            mouseenter: function() {

                                    this.addClass('hover');

                            },

                            mouseleave: function() {

                                    this.removeClass('hover');

                                    this.blur();

                            },

                            mousedown: function() {

                                    this.focus();

                            }

                    });


                    // Interactions for the 2 other buttons


                    document.id('$clearButton').addEvent('click', function() {

                            up.remove(); // remove all files

                            return false;

                    });


                    document.id('$uploadButton').addEvent('click', function() {

                            up.start(); // start upload

                            return false;

                    });

            }",




            'onFail'=> 'function(error) {

                            switch (error) {

                                    case "hidden": // works after enabling the movie and clicking refresh

                                            alert("Para habilitar o sistema de upload, desbloqueie no seu browser e atualize.");

                                            break;

                                    case "blocked": // This no *full* fail, it works after the user clicks the button

                                            alert("Para habilitar o sistema de upload, habilite o filme flash bloqueado");

                                            break;

                                    case "empty": // Oh oh, wrong path

                                            alert("O sistema de upload parece estar faltando, por favor, tente mais tarde");

                                            break;

                                    case "flash": // no flash 9+ <img src='http://www.yiiframework.com/forum/public/style_emoticons/default/sad.gif' class='bbc_emoticon' alt=':(' />

                                            alert("Precisa ter o plugin do Adobe Flash 9 ou superior para usar o upload")

                            }

                    }',


            'onFileSuccess'=> "function(file, response) {

                var json = new Hash(JSON.decode(response, true) || {});


                if (json.get('status') == '1') {

                        file.element.addClass('file-success');

                        file.info.set('html', '<strong>File sent:</strong> (' + json.get('width') + ' x ' + json.get('height') + 'px, <em>' + json.get('mime') + '</em>)');

                } else {

                        file.element.addClass('file-failed');

                        file.info.set('html', '<strong>Error sending:</strong> (' + (json.get('error') ? (json.get('error') + ' #' + json.get('code')) : response));

                }

            }",




            'onSelectFail'=> "function(files) {

                    files.each(function(file) {

                            new Element('li', {

                                    'class': 'validation-error',

                                    html: file.validationErrorMessage || file.validationError,

                                    title: MooTools.lang.get('FancyUpload', 'removeTitle'),

                                    events: {

                                            click: function() {

                                                    this.destroy();

                                            }

                                    }

                            }).inject(this.list, 'top');

                    }, this);

            }",




            /*'onFileComplete'=> "function(file) {

                    up.fileRemove(file);

            }",*/


            'onComplete'=>"function() {

               //document.id('fancy-status').setStyle('display','none');

               //up.remove();

               el = document.search('.file-success');

               for (i=0; i<el.length; i++){

                   el[i].destroy();

               }

            }",







//'onBeforeStart'=>"function() {

//var hash = {};

//document.cookie.split(/;\s*/).each(function(cookie) {

//cookie = cookie.split('=');

//if (cookie.length == 2) {

//hash[decodeURIComponent(cookie[0])] = decodeURIComponent(cookie[1]);

//}

//});

//

//up.setOptions({

//data: {cookieName: hash['myfield'], myfield: document.id('myfield').get('value')}

//});

//}",

        )


    ));

?>



Also,

When I add the code below, The widget don’t show anything. Y only see a blank page.


'YII_CSRF_TOKEN'=>Yii::app()->request->csrfToken),    //send your csrf token

 'appendCookieData'=>true,

In the controller/action:

The code below is in the file: /protected/controllers/CurriculumController.php




public function actionUploadedFiles() {

   echo "reached";

   $logFile = 'files/log.txt';  //be sure to adjust this path


   $result = array();

   if(count($_GET))   { $result[get] = $_GET; }

   if(count($_POST))  { $result[post] = $_POST; }

   if(count($_FILES)) { $result[files] = $_FILES; }


   //lets compare if $_POST['PHPSESSID'] really contains the session Id dumped in the lines above

   $result[mySessionId] = $_POST['PHPSESSID'];


   //here, starts the session with the same Id

   session_id($_POST['PHPSESSID']);

   session_start();


   //lets log so

   $log = @fopen($logFile, 'a');

   if ($log) {

      fputs($log, print_r($result, true) . "\n---\n");

      fclose($log);

   }


   //load the file and do whatever you need beyond this point

   $file = CUploadedFile::getInstanceByName("Filedata");

   $file->saveAs('files/'.$file->getName());


        echo json_encode($return);

    }



How can I do that?

I can acces directly to this widget, through the action. http://localhost/~di...m/uploadedFiles :rolleyes:

I added the action to the accessRules function of the controller.

I get the same error:

Also firebug throws other error:


File[1]::complete wasted!: ["Error #2038", "ioError", 0] Swiff.Uploader.js (line 370)[url=""][/url]


document.search is not a function

onComplete() index..../create (line 89)

run() mootoo...ancy.js (line 57)

el = document.search('.file-success');   index..../create (line 89)

Also,

I just try the same code with the version 1.0.9 and 1.1. And I get the same error.

ps: I have working only 2 weeks with the yii framework. Maybe there is something that you omitted to say and I don’t know…maybe.

I’m glad that I could help and happy that you got it working now :)

Thanks for sharing the issues!!

regards!!!

Which code of the widget and version of Yii are you using?

Because that don’t work for me… :unsure:

Luis, I’m preparing a complete working application with Yii 1.0.11 and I’ll post here soon, so that you can download it and try…once you’ve said that might be something wrong in your app, this way we can discover easily :)

regards!!

Luis, please, download the attached file and extract it to your webserver root directory (it is an application)

As I don’t know if you’re running Windows/Wamp or Linux/Apache, adjust anything to your needs in the following explanations

Things you have to do:

1 - extract the file

2 - adjust the path to your Yii directory in the index.php file (/www/fancy/index.php)




$yii=dirname(__FILE__).'/../yii1011r1579/framework/yii.php';



3 - be sure the following directories have writing permission (i suppose that your application directory is /www/fancy):

/www/fancy/assets

/www/fancy/protected/runtime

/www/fancy/uploads

4 - Access the application in your browser like http://localhost/fancy

I’ve added a new option in the default menu called Fancy Queue so you just have to click on it and the widget should be displayed

Try to upload some images and see if they’re saved in the /www/fancy/uploads directory

Besides, there will be a log file called “fancylog.txt” in the uploads directory. This log file tells you everything that happened with every file you’ve sent

Note: the application was built in Yii 1.0.11 r1579

Please, let me know what happens now

:)

Throws this error:


FancyUpload2 is not defined 

in the line 16 of http://localhost/fan...ite/fancyqueue:




var up = new FancyUpload2(document.id('fancy-status'), document.id('fancy-list'), {

:(

I’ve made some tests and got this error when I removed the line that includes FancyUpload2.js from the HTML code.

It seems like this file is not being loaded into your page

Could you please check in firebug if the sequence of loading scripts in the page is:

/fancy/assets/7826c02e/fancy/source/mootools-1_2_4-fancy.js

/fancy/assets/7826c02e/fancy/source/Fx.ProgressBar.js

/fancy/assets/7826c02e/fancy/source/Swiff.Uploader.js

/fancy/assets/7826c02e/fancy/source/FancyUpload2.js

text/javascript that creates fancy instance on the page

I’ve tested the application I sent you in a fresh Windows/Wamp/Firefox 3.6 installation and Linux/Apache Firefox 3.5.7

Also, please, perform the following test:

1 - download the attached file (it is from the official fancyupload website)

2 - unpack the file under your webroot folder

3 - access http://yourserver/the_unpacked_folder/build.html

The file contains a working fancyupload photoqueue demo in pure HTML/js from the official fancy website and should work fine. Then, try removing from build.html the line




	<script type="text/javascript" src="source/FancyUpload2.js"></script>



and see in firebug console if the same error is raised (this happened to me as the FancyError.png image attached shows)

What is the environment you’re trying to run the extension? Windows/Wamp, Linux/Apache or none of them?

Also, what’s the version of Firefox? have you tried in Chrome/IE/Opera?

Please, let me know what these tests show to you. Thanks

regards!!

:)

Hello scoob.junior,

I have news and good news,

Well I had tried the examples that you give me and it worked fine. The last error that I had, was in the assets folder. The files of the fancy uploader was incomplete. In that case the file fancyUpload2.js was missed. I added it and it works fine.

Then, I went to my orignal application and reviewed the assests folders, and the file ptBR_FancyUpload2.js missed. I added it.

Then I actived these lines of code in the view


'data'=>array('YII_CSRF_TOKEN'=>Yii::app()->request->csrfToken),    //send your csrf token

'appendCookieData'=>true,  //this will send PHPSESSID automatically

And also the error HTTP-302 was appeared. Y remember the function AccessRules, I added the string “uploadedFiles” to the proper allow array and it works! :rolleyes:

glory hallelujah!!

Thanks a lot scoob junior!

ps: I tried it with the 1.1 yii version.

Thank you for the extension! I also tried it with the 1.1 yii version and it works.

Could you please help me with another issue? I want to save the name of the uploaded file in an attribute called "image" of my model so that to get the requested path when I load the image…

I’ve checked the options of the extension but I didn’t find anything to connect the name of the file with the attribute.

Is there an easy way to do that?

Thank you in advance!

I have question,

scoob, the function UploadFiles in the controller, is called with each file of the queue or it is called one time?

that’s great, i’m very happy that it worked fine!! :)

thanks for sharing the information

ps. the file ptBR_FancyUpload2.js is just a pt_BR translation of FancyUpload2.js, I mean, some texts like “overall progress” and so…to use it, just rename it to FancyUpload2.js if you need :)

hey, Luis,

the action is called for each item in the queue, so you can treat each file separately in your controller/action

:)

hey, Vand,

in fact there is no option to link the file to an attribute, but you can do it in your controller/action

I suppose that you have the record in the database when you perform the upload (this is what I do around here), so it’s easy:

1 - in your view, when creating the fancy widget, add the id of your model to the option "data", like this:




'data'=>array('id'=>$model->id)



2 - in your controller/action upload, retrieve the value, load the model/attribute and save, like this:




$id = isset($_POST['id']) ? (int)$_POST['id'] : 0;

$model = Product::model()->findByPk($id);

$model->image = $file->getName();  //remember that $file is the existing instance of CUploadedFile

$model->save();



if you want to store the full Url or full Path, so, do something like:




...

//the url

$model->image = Yii::app()->baseUrl . DIRECTORY_SEPARATOR . 'images' . DIRECTORY_SEPARATOR . $file->getName();


//or even the physical path

$model->image = dirname(Yii::app()->getBasePath()) . DIRECTORY_SEPARATOR . 'images' . DIRECTORY_SEPARATOR . $file->getName();

...



I’m not sure if this is what you want to do, hope it helps…

if you have any other questions, please, feel free to ask, right?

regards!!

:)

Thank you for your reply.

I tried it but got the following error

Fatal error: Call to undefined method stdClass::save() in C:\wamp\www\travelPedia\protected\controllers\SiteController.php on line 120

Do you know what might be wrong?

I have a model called Articles and it has the attribute "image" so in the SiteController where I have the upload action I wrote:


 

            $id = isset($_POST['id']) ? (int)$_POST['id'] : 0;

            $model = Articles::model()->findByPk($id);

            $model->image = $file->getName();  //remember that $file is the existing instance of CUploadedFile

            $model->save();



If I put the action code in ArticlesController the uploading returns an HTTP-Status 500 error…

I don’t have much experience and I’m new to the framework so maybe I’m doing something wrong…

I would appreciate it if you could help me with that.

Thank you