在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商品图片多文件上传 
于是我尝试阅读并理解它的原代码,知道了原来在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'); ?>
 
如果一切顺利,则会在自定义的后台页面中输出看到这两个按钮: 
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多文件上传代码功能开发的更多相关文章

  1. php实现文件上传下载功能小结

    文件的上传与下载是项目中必不可少的模块,也是php最基础的模块之一,大多数php框架中都封装了关于上传和下载的功能,不过对于原生的上传下载还是需要了解一下的.基本思路是通过form表单post方式实现 ...

  2. JavaWeb实现文件上传下载功能实例解析

    转:http://www.cnblogs.com/xdp-gacl/p/4200090.html JavaWeb实现文件上传下载功能实例解析 在Web应用系统开发中,文件上传和下载功能是非常常用的功能 ...

  3. JavaWeb实现文件上传下载功能实例解析 (好用)

    转: JavaWeb实现文件上传下载功能实例解析 转:http://www.cnblogs.com/xdp-gacl/p/4200090.html JavaWeb实现文件上传下载功能实例解析 在Web ...

  4. 多文件上传 iOS功能

    多文件上传 iOS功能,原文来自ios教程网整理的,大家可以看看演示:ios.662p.com ,喜欢的朋友可以看看我的博客吧. NSURL* url = [NSURL URLWithString:@ ...

  5. servlet3.0获取参数与文件上传代码示例

    转: servlet3.0获取参数与文件上传代码示例 2018年08月26日 20:25:35 苏凯勇往直前 阅读数:98   package com.igeek.servlet;   import ...

  6. php文件上传代码解析

    php文件上传代码解析 is_uploaded_file()  //函数判断指定的文件是否是通过 HTTP POST 上传的,返回一个布尔值. $_FILES['upfile']['tmp_name' ...

  7. 实现多文件上传在iOS开发中

    该功能实现了实现多文件上传在iOS开发中,喜欢的朋友可以研究一下吧. NSURL* url = [NSURL URLWithString:@"xxx"]; ASIFormDataR ...

  8. ASP.NET访问网络映射盘&实现文件上传读取功能

    最近在改Web的时候,遇到一个问题,要跨机器访问共享文件夹,以实现文件正常上传下载功能. 要实现该功能,可以采用HTTP的方式,也可以使用网络映射磁盘的方式,今天主要给大家分享一下使用网络映射磁盘的方 ...

  9. WEB文件上传下载功能

    WEB文件上传下载在日常工作中经常用到的功能 这里用到JS库 http://files.cnblogs.com/meilibao/ajaxupload.3.5.js 上传代码段(HTML) <% ...

随机推荐

  1. 递归算法(一)——akm

    要求 已知akm函数如下: { n+1 while m=0 }                          => Rule I akm(m,n)= { akm(m-1,1) while n ...

  2. Facebook 内部高效工作PPT

    Facebook 内部分享:不论你如何富有,你都赚不到更多的时间,你也回不到过去.没有那么多的假如,只有指针滴答的时光飞逝和你应该好好把握的现在,以下26张PPT的分享将为您带来时间价值管理的技巧. ...

  3. Play framework 2.0 -应用程序全局设置(转)

    转载自: http://shenbai.iteye.com/blog/1517366 1.全局对象 在工程中定义全局对象可以允许你操作你的应用程序的全局设置.这个全局对象必须定义在根包下. impor ...

  4. 执行MAVEN更新包

    我们一般使用 mvn eclipse:eclipse 执行对maven库的引用,这样会修改项目下的classpath文件. 我们修改直接在eclipse 使用maven库作为项目的引用. 步骤如下: ...

  5. 对Docker的价值和应用场景分析

    近年来,Docker在IT界可谓风光十足,各大技术论坛上赚足了眼球,公司内外也有相当多的介绍和尝试,看上去如此高大上的技术,貌似会给云.服务部署.运维等领域带来颠覆性的创新. 近期查阅了一些文档,较深 ...

  6. Android 获取网络状态

    1.检测网络是否可用 public boolean isNetWorkConnected() { ConnectivityManager cm = (ConnectivityManager)getSy ...

  7. Autolayout-VFL语言添加约束

    一.VFL语言简洁 VFL(Visual format language)语言是苹果为了简化手写Autolayout代码所创建的专门负责编写约束的代码.为我们简化了许多代码量. 二.使用步骤 使用步骤 ...

  8. SharePoint 沙盒解决方案 VS 场解决方案

    博客地址 http://blog.csdn.net/foxdave 最近看书正好看到了关于沙盒解决方案的介绍,便整理记录一下. 虽然沙盒解决方案已经在最新的SharePoint开发中被否决弃用了(被A ...

  9. win8系统 host文件无法修改解决之道

    host文件,路径为:C:\windows\system32\drivers\etc\hosts 方法/步骤: 方法1:用notepad++打开host文件,修改和保存 方法2:(1)首先用管理管权限 ...

  10. 将Ajax 中数组转换成字符串 封装成类

    <?php class Ajax{ //ajax调用的方法 //sql是要执行的语句 //$type是SQL语句的类型,0代表增删改,1代表查询 //$db代表要操作的数据 public fun ...