实现Magento多文件上传代码功能开发

在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多文件上传功能实现的解决思路,希望能对看到的你有帮助!

时间: 2024-11-05 17:23:48

实现Magento多文件上传代码功能开发的相关文章

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

转:http://www.cnblogs.com/xdp-gacl/p/4200090.html JavaWeb实现文件上传下载功能实例解析 在Web应用系统开发中,文件上传和下载功能是非常常用的功能,今天来讲一下JavaWeb中的文件上传和下载功能的实现. 对于文件上传,浏览器在上传的过程中是将文件以流的形式提交到服务器端的,如果直接使用Servlet获取上传文件的输入流然后再解析里面的请求参数是比较麻烦,所以一般选择采用apache的开源工具common-fileupload这个文件上传组件

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

转: 转:http://www.cnblogs.com/xdp-gacl/p/4200090.html JavaWeb实现文件上传下载功能实例解析 在Web应用系统开发中,文件上传和下载功能是非常常用的功能,今天来讲一下JavaWeb中的文件上传和下载功能的实现. 对于文件上传,浏览器在上传的过程中是将文件以流的形式提交到服务器端的,如果直接使用Servlet获取上传文件的输入流然后再解析里面的请求参数是比较麻烦,所以一般选择采用apache的开源工具common-fileupload这个文件上

用Fine Uploader+ASP.NET MVC实现ajax文件上传[代码示例]

Fine Uploader(http://fineuploader.com/)是一个实现 ajax 上传文件的 Javascript 组件. This project attempts to achieve a user-friendly file-uploading experience over the web. It's built as a Javascript plugin for developers looking to incorporate file-uploading int

文件上传代码

1.0先在页面上初始化 代码 <title>文件上传</title> </head> <body> <form enctype="multipart/form-data" action="test.jsp" method="post"> 名称:<input type="text" name="username" /><br>

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

最近在改Web的时候,遇到一个问题,要跨机器访问共享文件夹,以实现文件正常上传下载功能. 要实现该功能,可以采用HTTP的方式,也可以使用网络映射磁盘的方式,今天主要给大家分享一下使用网络映射磁盘的方式,来跨机器访问共享文件夹. 解决方案:   本以为只要在Web服务器做一下磁盘映射,然后把该映射盘符当做本地磁盘来使用就可以了,但是却一直有问题,查找了一下资料,是因为IIS默认账户为NETWORK_SERVICE,该账户是没权限访问共享目录的,所以当我们把站点部署到IIS上的时候,再访问映射磁盘

基于Java的一个简单的文件上传下载功能

最近在公司给客户端做接口,有一个图片上传和文件下载的功能,本来想用Struts来做文件上传下载,但是看了下公司好像没有这个配置,然后看了下同事的代码,才发现原来Apache也可以简单的实现文件上传下载. 首先引入commons-io-2.2.jar FileUtils为我们提供了很多对文件的操作的方法,比如上传整个文件夹的文件.上传单个文件等 然后请看代码下载: public static void uploadFile(String targetDirectory,String targetF

(0423) 简单文件上传代码

1.文件上传的原理:将客户端的文件上传到服务器端,再讲服务器端的临时文件移动到指定目录. 2.代码: <form action="chulifile1.php" method="post" enctype="multipart/form-data"> <input type="file" name="files"/> <input type="submit"

servlet3.0的文件上传代码配置怎么写

之前学习过xml配置servlet3.0的文件上传,但是变成code方式一直不知道怎么弄,相比较起来apache的文件上传配置和xml倒是没什么太大区别. 直接上代码:无需依赖,只要一个方法就好了customizeRegistration() public class SystemConfig extends AbstractAnnotationConfigDispatcherServletInitializer { @Override protected Class<?>[] getRoot

html5+java大文件上传代码

<body> <input id="fileid" type="file" accept="video/*;capture=camera" onchange="onfile(this)"> <input id="btn" type="button" value="提交"> <script type="text/jav