Tag Archives: flex uploader

Why Magento Flex uploader won’t show your selected files?

If you hurry, then just scroll down until the end of the article to see the solution.

In the last couple of hours I tried to figure this out, because it was really ugly to select some files to upload and then see nothing selected (even if it was selected in the javascript object).
First of all I wanted to make myself sure that everything is configured well, so I’ve opened my previous article about how to use the Magento Flex uploader. Everything was nice, even after the second look. Then it got in my mind that the file uploading shows nicely the selected files before uploading. Compared the code… everything looked good. As a last try I began looking into the flash component’s source code and into the associated javascripts. And the miracle has happened. I simply couldn’t believe it. The reason why it was not working was the undefined maxUploadFileSize javascript variable. Incredible, isn’t it? Lets see the short explanation:

1. after pressing the browse button and when the files are selected, the handleSelect method will be called (we are talking about the Flex.Uploader javascript class which is located in flexuploader.js)

2. handleSelect looks like this:

handleSelect: function (event) {
            this.files = event.getData().files;
            this.checkFileSize();
            this.updateFiles();
            this.getInnerElement('upload').show();
            if (this.onFileSelect) {
                this.onFileSelect();
            }
        },

the problem occurs while trying to call the checkFileSize method.

3. lets see what is there:

checkFileSize: function() {
            newFiles = [];
            hasTooBigFiles = false;
            this.files.each(function(file){
                if (file.size > maxUploadFileSizeInBytes) {
                    hasTooBigFiles = true;
                    this.uploader.removeFile(file.id)
                } else {
                    newFiles.push(file)
                }
            }.bind(this));
            this.files = newFiles;
            if (hasTooBigFiles) {
                alert(
                    this.translate('Maximum allowed file size for upload is')+' '+maxUploadFileSize+".n"+this.translate('Please check your server PHP settings.')
                );
            }
        },

do you see the bolded variables? There are no checks whether the maxUploadFileSizeInBytes or the maxUploadFileSize is defined. When the code execution reaches these checks, it simply breaks the code execution, so handleSelect won’t ever run the remained code.

So for those who just came here and scrolled down for a quick solution:

Define maxUploadFileSizeInBytes and maxUploadFileSize javascript variables in your code, something like this:

    var maxUploadFileSizeInBytes = 2097152;
    var maxUploadFileSize = '2M';

That’s all.

Using Magento Flex uploader

A few days ago I tried to use Uploadify in Magento, but it failed because of jQuery noConflict, so I decided to try Magento’s default uploader, the Flex Uploader.

I couldn’t find a good documentation or tutorial about it, so I did a little research.

In the template you should put:

<?php $htmlId = "someHtmlId"; ?>
 <div id="<?php echo $htmlId ?>" class="uploader">
     <div class="buttons">
        <div id="<?php echo $htmlId ?>-install-flash" style="display:none">
            <?php echo Mage::helper('media')->__('This content requires last version of Adobe Flash Player. <a href="%s">Get Flash</a>', 'http://www.adobe.com/go/getflash/') ?>
        </div>
     </div>
     <div class="clear"></div>
     <div id="<?php echo $htmlId ?>-template" class="no-display">
         <div id="{{id}}" class="file-row">
             <span class="file-info">{{name}} ({{size}})</span>
             <span class="delete-button"><button id="{{id}}-delete" title="<?php echo $this->__("Delete")?>" type="button" class="scalable delete" onclick="uploader.removeFile('{{fileId}}')" style=""><span><span><span><?php echo $this->__("Delete") ?></span></span></span></button></span>
             <span class="progress-text"></span>
             <div class="clear"></div>
         </div>
     </div>
     <div id="<?php echo $htmlId ?>-template-progress" class="no-display">
         {{percent}}% {{uploaded}} / {{total}}
     </div>
 </div>

Practically this will be the place where the uploader will show you the progress of the upload. You will also need to place a javascript code which should look like:

    var uploader = new Flex.Uploader('<?php echo $htmlId ?>', '<?php echo $this->getSkinUrl('media/uploader.swf') ?>', <?php echo $this->getConfigJson('some_parameter_for_you') ?>);
    uploader.onFilesComplete = function(completedFiles)
    {
        completedFiles.each(function(file)
            {
                doSomethingWithTheResponse(file.response);
                uploader.removeFile(file.id);
            }
        );
        MediabrowserInstance.handleUploadComplete();
    }
    // hide flash buttons
    if ($('<?php echo $htmlId ?>-flash') != undefined)
    {
        $('<?php echo $htmlId ?>-flash').setStyle({float:'left'});
    }
//specify maximum file upload size (very important!)
    var maxUploadFileSizeInBytes = 10 * 1024 * 1024;
    var maxUploadFileSize = '10M';

 

Attention! $ is Prototype (not jQuery) in the example above.

We will need to configure the Flex uploader in the block class of the template file:

    public function getConfigJson($field)
    {
        $this->getConfig()->setParams(
            array(
                'form_key' => $this->getFormKey(),
                "field" => $field
            )
        );
        $this->getConfig()->setFileField('Filedata');
        $this->getConfig()->setUrl(Mage::getModel('adminhtml/url')->addSessionParam()->getUrl("*/*/upload", array("param1" => "value1")));
        $this->getConfig()->setFilters(array(
            'pdf documents' => array(
                'label' => Mage::helper('adminhtml')->__('Portable Document Format (.pdf)'),
                'files' => array('*.pdf')
            )
        ));
        return Mage::helper('core')->jsonEncode($this->getConfig()->getData());
    }     

    public function getConfig()
    {
        if(is_null($this->_config)) {
            $this->_config = new Varien_Object();
        }

        return $this->_config;
    }

You can specify multiple file filters with the setFilters method, not just one as in my example. Also, with the setUrl method you will set the target URL, which will do the processing of the upload. In my example I set it as */*/upload. This means that in the controller of the current page you will have to set something similar to this:

    public function uploadAction()
    {
        if (!empty($_FILES))
        {
            $result = array();
            try
            {
                $uploader = new Varien_File_Uploader("Filedata");
                $uploader->setAllowRenameFiles(true);

                $uploader->setFilesDispersion(false);
                $uploader->setAllowCreateFolders(true);

                $path = "put_your_path_to_save_here";//ex. Mage::getBaseDir('base') . DS ."my_uploads" . DS

                $uploader->setAllowedExtensions(array('pdf')); //server-side validation of extension
                $uploadSaveResult = $uploader->save($path, $_FILES['Filedata']['name']);

                $result = $uploadSaveResult['file'];
            }
            catch(Exception $e)
            {
                $result = array(
                    "error" => $e->getMessage(),
                    "errorCode" => $e->getCode(),
                    "status" => "error"
                );
            }             
            $this->getResponse()->setBody(Mage::helper('core')->jsonEncode($result));
        }
    }

Don’t forget to load the required javascript libraries. You can do it in your layout xml file:

   <your_layout>
        <reference name="head">
            <action method="addJs">
                <js>lib/flex.js</js>
            </action>
            <action method="addJs">
                <js>lib/FABridge.js</js>
            </action>
            <action method="addJs">
                <js>mage/adminhtml/flexuploader.js</js>
            </action>
        </reference>
   </your_layout>
   

That’s all folks!