2 /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
4 // +----------------------------------------------------------------------+
5 // | Akelos Framework - http://www.akelos.org |
6 // +----------------------------------------------------------------------+
7 // | Copyright (c) 2002-2006, Akelos Media, S.L. & Bermi Ferrer Martinez |
8 // | Released under the GNU Lesser General Public License, see LICENSE.txt|
9 // +----------------------------------------------------------------------+
14 * @author Bermi Ferrer <bermi a.t akelos c.om>
15 * @copyright Copyright (c) 2002-2006, Akelos Media, S.L. http://www.akelos.org
16 * @license GNU Lesser General Public License <http://www.gnu.org/copyleft/lesser.html>
20 require_once(AK_LIB_DIR
.DS
.'AkActionView'.DS
.'AkActionViewHelper.php');
22 class FileUploadHelper
extends AkActionViewHelper
24 function _instantiateCacheHandler()
26 if(empty($this->Cache
)){
27 require_once(AK_LIB_DIR
.DS
.'AkCache.php');
28 $this->Cache
=& new AkCache();
29 $this->Cache
->init(3600*2);
34 * Handles a gmail-like file upload.
36 * Just add this code at the beigining of the form action receiver.
38 * if($this->file_upload_helper->handle_partial_upload('/tmp')){ // where /tmp is the temporary directory for uploaded files
42 * You must add this javascript to your view:
44 * <script src="/javascripts/file_uploader.js" type="text/javascript"></script>
45 * <script type="text/javascript">
46 * window.onload = function(){
47 * FileUploader.start('form_id', {partial:true}); // Change "form_id" for the id you supplied to your form
51 * @param bool $send_json_response
53 function handle_partial_upload($temporary_directory = AK_TMP_DIR
, $send_json_response = true)
55 $this->_instantiateCacheHandler();
57 $this->_setTempDir($temporary_directory);
59 // Perform some garbage collection
60 $this->clean_persisted_files();
62 // If we are uploading files from the special iframe we store the file on the cache for using it later
63 if($this->_controller
->Request
->isPost() && !empty($this->_controller
->params
['__iframe_file_uploader_call_from'])){
64 $uploaded_files = $this->_handle_partial_files($this->_controller
->params
);
65 if($send_json_response){
66 $this->_controller
->layout
= false;
67 $this->_controller
->renderText(Ak
::toJson($uploaded_files));
69 $this->_controller
->params
= array_merge($this->_controller
->params
, $uploaded_files);
74 // We are requesting the file for downloading
75 }elseif (!$this->_controller
->Request
->isPost() && !empty($this->_controller
->params
['persistence_key'])){
76 $this->_send_file($this->_controller
->params
['persistence_key']);
80 // We have "persisted_keys" into the post so lets look for them and populate the params with cached data
81 }elseif ($this->_controller
->Request
->isPost() && !empty($this->_controller
->params
['persisted_keys'])){
82 if(!empty($this->_controller
->params
['persisted_files'])){
83 $files = $this->_get_persisted_files_params($this->_controller
->params
['persisted_files']);
84 $this->_controller
->params
= array_merge_recursive($this->_controller
->params
, $files);
85 $this->_clean_up_persisted_on_shutdown($this->_controller
->params
['persisted_keys']);
86 unset($this->_controller
->params
['persisted_keys']);
87 unset($this->_controller
->params
['persisted_files']);
96 function _get_persisted_files_params($params)
99 foreach ($params as $name=>$details){
100 if(is_string($details)){
101 $result[$name] = $this->_get_file_details($details);
102 }elseif(is_array($details)){
103 $_nested = $this->_get_persisted_files_params($details);
104 if(!empty($_nested)){
105 $result = array_merge(array($name=>$_nested), $result);
112 function _get_file_details($key)
114 $key = preg_replace('/[^A-Z^a-z^0-9]/','',$key);
115 $file = $this->get_persisted_file($key);
117 Ak
::file_put_contents($this->_getTempDir().DS
.'_file_uploader_file_'.$key, base64_decode($file['contents']), array('ftp'=>false));
118 return array('tmp_name'=>$this->_getTempDir().DS
.'_file_uploader_file_'.$key,'size'=>$file['size'], 'name'=>$file['name'],'type'=>$file['type'], 'error'=>0);
124 function _getTempDir()
126 return $this->temp_dir
;
129 function _setTempDir($temp_dir)
131 $temp_dir = rtrim($temp_dir,'/\\');
132 $tmp_file = @tempnam
($temp_dir,'testing');
133 if($tmp_file && @unlink
($tmp_file)){
134 $this->temp_dir
= $temp_dir;
136 trigger_error(Ak
::t("You cant use the directory %dir for temporary storing files uploaded",array('%dir'=>$temp_dir)), E_USER_ERROR
);
140 function _handle_partial_files($params)
143 foreach ($params as $name=>$details){
144 if(is_array($details) && !empty($details['name']) && !empty($details['tmp_name']) && !empty($details['size'])){
145 $details['persistence_key'] = md5($details['tmp_name']);
146 $details['human_size'] = $this->_controller
->number_helper
->human_size($details['size']);
147 $file = $this->Cache
->get($details['persistence_key'], 'persistent_files');
149 $this->Cache
->save(serialize(array_merge($details,array('contents'=>base64_encode(file_get_contents($details['tmp_name']))))));
151 $result[$name] = $details;
152 }elseif(is_array($details)){
153 $_nested = $this->_handle_partial_files($details);
154 if(!empty($_nested)){
155 $result = array_merge(array($name=>$_nested), $result);
162 function get_persisted_file($persistence_key)
164 $file = $this->Cache
->get($persistence_key, 'persistent_files');
168 return unserialize($file);
171 function delete_persisted_file($key)
173 $key = preg_replace('/[^A-Z^a-z^0-9]/','',$key);
174 $this->Cache
->remove($key, 'persistent_files');
177 function clean_persisted_files()
179 $this->Cache
->clean('persistent_files', 'old');
182 function _send_file($key)
184 $key = preg_replace('/[^A-Z^a-z^0-9]/','',$key);
185 $file = $this->get_persisted_file($key);
187 $send_method = $file['size'] > 1048576 ?
'sendDataAsStream' : 'sendData';
188 $this->_controller
->$send_method(base64_decode($file['contents']),array('length'=>$file['size'], 'filename'=>$file['name'],'type'=>$file['type']));
195 function _clean_up_persisted_on_shutdown($keys = false)
199 foreach ($key_cache as $key){
200 @unlink
($this->_getTempDir().DS
.'_file_uploader_file_'.$key);
201 $this->delete_persisted_file($key);
205 if(empty($key_cache)){
206 register_shutdown_function(array(&$this,'_clean_up_persisted_on_shutdown'));
208 $key_cache = array_merge($key_cache, $keys);