Magento多文件上传代码功能实现
2015-03-18 19:18
411 查看
前言
在Magento中上传单个文件很简单,可以直接在继承的Mage_Adminhtml_Block_Widget_Form类中直接添加如下组件Field:
对于图片:
$fieldset->addField('test_pic', 'image', array( 'label' => "标签", 'name' => 'test_pic', ));
对于文件:
$fieldset->addField('test_file', 'file', array( 'label' => "标签", 'name' => 'test_file', ));
处理时只需在对应后台的控制器action中使用
Varien_File_Uploader工具类来进行获取。
但这个组件只能处理单文件上传,那么对于多文件上传该怎么做呢?通过观察原Magento功能可知,只有在商品的编辑或创建时,有一个上传多图片的功能(见下图),该功能实现的就是多文件上传!
于是我尝试阅读并理解它的原代码,知道了原来在Magento中处理多文件上传使用的是一个叫Flex Uploader的Flash插件实现的,并且对应的Magento系统给了一个封装好的Block类进行处理:
Mage_Adminhtml_Block_Media_Uploader,下面就个人所实现的一个多文件上传插件来谈谈具体实现步骤。
1.首先,实现Block类
在实现多文件上传时,需要先实现前台HTML页面,这里通过自定一个Block类来包含Flex Uploader组件来实现,这个类可以继承普通的后台Block类:Mage_Adminhtml_Block_Widget,如下在其重置的
_prepareLayout方法中添加
Mage_Adminhtml_Block_Media_Uploader子块Block:
protected function _prepareLayout() { // 添加Mage_Adminhtml_Block_Media_Uploader子块Block $this->setChild('uploader', $this->getLayout()->createBlock('adminhtml/media_uploader')); $this->getChild('uploader')->getConfig() // 文件上传处理action ->setUrl(Mage::getModel('adminhtml/url')->addSessionParam()->getUrl('*/material/upload')) ->setFileField('material_files') ->setFilters(array( 'all' => array( 'label' => Mage::helper('adminhtml')->__('All Files'), 'files' => array('*.*') // 说明接收任意后缀的文件 ) )); return parent::_prepareLayout(); }
相应的在该Block类对应的phtml视图模板中输出这个名为
uploader的子块:
<?php echo $this->getChildHtml('uploader'); ?>
如果一切顺利,则会在自定义的后台页面中输出看到这两个按钮:
如上Block代码参考:
Mage_Adminhtml_Block_Catalog_Product_Helper_Form_Gallery_Content
如上phtml模板参考:
app\design\adminhtml\default\default\template\catalog\product\helper\gallery.phtml
2.实现上传处理Action
当你在页面上看到了这两个按钮,说明你的页面已经成功的添加了Flex Uploader插件,接着我们就需要实现对应的后台上传处理Action,还记得上面的setUrl(url)方法吗?该方法指定的就是当用户选择好了文件后,点击“上传文件”按钮接收文件的Action Url,这里我们设定的是一个名这
upload的action,下面可以给出其处理的代码:
public function uploadAction() { try { // 注意这里的material_files与上面Block中setFileField()方法设置的是同一个名称 $uploader = new Mage_Core_Model_File_Uploader('material_files'); // 允许的上传文件后缀名,这里注释掉说明允许所有后缀文件,当然了后缀名为PHP的是禁止的 // $uploader->setAllowedExtensions(array('txt', 'pdf', 'doc', 'docx')); $uploader->setAllowRenameFiles(true); $uploader->setFilesDispersion(true); $result = $uploader->save($this->getBaseTmpMediaPath()); // Mage::log($result, null, 'commodity___test.log'); /** * Workaround for prototype 1.7 methods "isJSON", "evalJSON" on Windows OS */ $result['tmp_name'] = str_replace(DS, "/", $result['tmp_name']); $result['path'] = str_replace(DS, "/", $result['path']); $result['url'] = $this->getTmpMediaUrl($result['file']); $result['file'] = $result['file']; $result['cookie'] = array( 'name' => session_name(), 'value' => $this->_getSession()->getSessionId(), 'lifetime' => $this->_getSession()->getCookieLifetime(), 'path' => $this->_getSession()->getCookiePath(), 'domain' => $this->_getSession()->getCookieDomain() ); } catch (Exception $e) { $result = array('error' => $e->getMessage(), 'errorcode' => $e->getCode()); } // Mage::log($result, null, 'commodity___test.log'); $this->getResponse()->setBody(Mage::helper('core')->jsonEncode($result)); } private function getBaseTmpMediaPath() { return Mage::getBaseDir('media') . DS . 'commodity' . DS . 'material'; } private function getTmpMediaUrl($file) { $file = str_replace(DS, '/', $file); if (substr($file, 0, 1) == '/') { $file = substr($file, 1); } return Mage::getBaseUrl('media') . '/commodity/material/' . $file; }
可以看到,处理上传文件,使用的是一个名为
Mage_Core_Model_File_Uploader的工具类处理,而传给前台的就编码后的JSON信息,也就是说,Flex Uploader插件通过Ajax上传的每一个文件。
通过放开
Mage::log()方法,我们可以进一步的了解到
Mage_Core_Model_File_Uploader工具类调用
save方法后,返回的数据格式如下:
Array ( [name] => 文件名.后缀 [type] => application/octet-stream [tmp_name] => <apache设定临时目录>\tmp\phpBA95.tmp [error] => 0 [size] => 4907 [path] => <Magento根目录>\media\commodity\material [file] => /v/i/重命名文件名.后缀 )
上面的就是最初的
$result变量的值 ,当然了我进行了一些自定义的处理使
$result变量更加符合我插件的格式数据,你也可以根据自己的情况自定义处理。
如上代码参考:
Mage_Adminhtml_Catalog_Product_GalleryController
3.前台AJAX接收JSON处理
如上,有了前台页面,后台上传处理action,接下来我们要做的就是能够在前台页面中接收处理上面upload action中返回的JSON信息,对于这个Flex Uploader插件,我们应该怎么接收JSON呢?通过查看
<Magento根目录>\js\mage\adminhtml\flexuploader.jsJS文件我们知道了,Flex Uploader插件的上传成功回调函数是
onFilesComplete;要接收后台上面的JSON信息,我们只需要设置当前页面下的
Flex.Uploader实例对象的
onFilesComplete方法。
那问题又来了,我们该如何得到当前页面的
Flex.Uploader实例对象呢?
其实Magento早为我们准备好了,你还记得上面Block类中的子Block
uploader对象吗?通过它我们就可以得到
Flex.Uploader实例对象,具体的代码如下(在phtml模板的
<script>标签中):
<script type="text/javascript"> var uploader = <?php echo $this->getChild('uploader')->getJsObjectName(); ?>; uploader.onFilesComplete = function(files) { // 接收处理上传成功能的JSON数据 } </script>
如上代码参考:
<Magento根目录>\js\mage\adminhtml\product.js中的
handleUploadComplete方法。
4.最后
根据上面的粗略介绍我想应该能给大家使用Flex Uploader插件上传多文件有一定的启示,最后的一步就是要将得到上传返回的JSON信息在前台使用hidden保存起来,再通过对应的form上传给后台操作写入数据库,实现最后的收尾工作;在这里可以参考<Magento根目录>\js\mage\adminhtml\product.js中的方法,将JSON信息转化为字符串保存,对应后台在使用JOSN解码得到对象数组操作处理。
在最最后还有一点小小的问题,就是在单个页面中如何保含多个Flex Uploader插件,这种情况可能在Magento后台使用Tab组件中遇到。当在一个页面中使用多个Flex Uploader插件,我们就不能直接的使用
Mage_Adminhtml_Block_Media_Uploader子块Block中设定的
media/uploader.phtml模板了,因为
media/uploader.phtml模板中包含有引入Flex Uploader插件依赖JS文件:
<?php echo $this->helper('adminhtml/js')->includeScript('lib/flex.js') ?> <?php echo $this->helper('adminhtml/js')->includeScript('mage/adminhtml/flexuploader.js') ?> <?php echo $this->helper('adminhtml/js')->includeScript('lib/FABridge.js') ?>
单在同一个页面中使用多个Flex Uploader插件时,这三个JS会重复执行多次,故而操作中会出现错误。
解决办法是在前台的自定义Block类中给
Mage_Adminhtml_Block_Media_Uploader子块设定去掉JS引入代码的phtml模块,像这样在Block中的
_prepareLayout()方法中为子块
uploader指定自定义phtml模板:
$this->getChild('uploader')->setTemplate('自定义/uploader.phtml')->getConfig()
最后在Tabs Block中的
_prepareLayout()方法统一引用Flex Uploader插件依赖JS文件:
protected function _prepareLayout() { // Flash多文件上传插件Flex Uploader $this->getLayout()->getBlock('head')->addJs('lib/flex.js'); $this->getLayout()->getBlock('head')->addJs('mage/adminhtml/flexuploader.js'); $this->getLayout()->getBlock('head')->addJs('lib/FABridge.js'); return parent::_prepareLayout(); }
如上就是关于Magento多文件上传功能实现的解决思路,希望能对看到的你有帮助!
相关文章推荐
- 实现Magento多文件上传代码功能开发
- Jquery AjaxUpload实现文件上传功能代码实例教程
- Servlet+Jsp实现图片或文件的上传功能具体思路及代码
- Java实现FTP文件的上传和下载功能的实例代码
- php利用iframe实现无刷新文件上传功能的代码
- SpringMVC+Ajax实现文件批量上传和下载功能实例代码
- html5拍照功能实现代码(htm5上传文件)
- C#实现文件上传及文件下载功能实例代码
- Ajax配合Spring实现文件上传功能代码
- PHP实现文件上传功能实例代码
- Java代码使用FTPClient实现ftp文件上传下载和删除的功能
- php实现文件上传功能的代码实例
- HTML5拖拽文件到浏览器并实现文件上传下载功能代码
- Jquery AjaxUpload实现文件上传功能代码实例教程
- java实现图片或文件的上传功能具体思路及代码
- 使用IO技术,创建一个目录,然后复制一个文件到该目录!实现复制的功能。(在博客园上传的第一份代码)
- Java与WebUploader相结合实现文件上传功能(实例代码)
- 移动端HTML5实现文件上传功能【附代码】
- PHP 文件上传功能实现代码
- java文件上传下载功能实现代码