4 * Based on a example from Alastair Dawson
6 * @link http://blog.vixiom.com/2006/09/08/multiple-file-upload-with-flash-and-ruby-on-rails/
7 * @author Alastair Dawson
8 * @author Andreas Gohr <andi@splitbrain.org>
12 import mx
.utils
.Delegate
;
14 import mx
.controls
.DataGrid;
15 import mx
.controls
.gridclasses
.DataGridColumn
16 import mx
.controls
.Button;
17 import mx
.controls
.TextInput;
18 import mx
.controls
.CheckBox;
19 import mx
.controls
.Label;
21 import flash
.net
.FileReferenceList;
22 import flash
.net
.FileReference;
24 class MultipleUpload
{
26 private var fileRef
:FileReferenceList;
27 private var fileRefListener
:Object;
28 private var list
:Array;
31 private var files_dg
:DataGrid;
32 private var browse_btn
:Button;
33 private var upload_btn
:Button;
34 private var ns_input
:TextInput;
35 private var ns_label
:Label;
36 private var overwrite_cb
:CheckBox;
38 private var url
:String;
39 private var upurl
:String;
40 private var current
:Number;
41 private var done
:Number;
42 private var lasterror
:String;
47 * Initializes the needed objects and stage objects
49 public function MultipleUpload
(fdg
:DataGrid, bb
:Button, ub
:Button, nsi
:TextInput, nsl
:Label, ob
:CheckBox) {
50 // references for objects on the stage
58 // file list references & listener
59 fileRef
= new FileReferenceList();
60 fileRefListener
= new Object();
61 fileRef
.addListener
(fileRefListener
);
69 * Initializes the User Interface
71 * Uses flashvars to access possibly localized names
73 private function iniUI
() {
74 // register button handlers
75 browse_btn
.onRelease
= Delegate
.create
(this, this.browse
);
76 upload_btn
.onRelease
= Delegate
.create
(this, this.upload
);
78 // columns for dataGrid
79 var col
:DataGridColumn;
80 col
= new DataGridColumn('name');
81 col
.headerText
= ( _root
.L_gridname
? _root
.L_gridname
: 'Filename' );
83 files_dg
.addColumn
(col
);
84 col
= new DataGridColumn('size');
85 col
.headerText
= ( _root
.L_gridsize
? _root
.L_gridsize
: 'Size' );
87 files_dg
.addColumn
(col
);
88 col
= new DataGridColumn('status');
89 col
.headerText
= ( _root
.L_gridstat
? _root
.L_gridstat
: 'Status' );
91 files_dg
.addColumn
(col
);
94 if(_root
.L_overwrite
) overwrite_cb
.label
= _root
.L_overwrite
;
95 if(_root
.L_browse
) browse_btn
.label
= _root
.L_browse
;
96 if(_root
.L_upload
) upload_btn
.label
= _root
.L_upload
;
97 if(_root
.L_namespace
) ns_label
.text
= _root
.L_namespace
;
99 // prefill input field
100 if(_root
.O_ns
) ns_input
.text
= _root
.O_ns
;
103 upload_btn
.enabled
= false;
104 if(!_root
.O_overwrite
) overwrite_cb
.visible
= false;
106 // initalize the data provider list
109 files_dg
.spaceColumnsEqually
();
113 * Open files selection dialog
115 * Adds the allowed file types
117 private function browse
() {
118 if(_root
.O_extensions
){
119 var exts
:Array = _root
.O_extensions
.split
('|');
120 var filter
:Object = new Object();
121 filter
.description
= (_root
.L_filetypes
? _root
.L_filetypes
: 'Allowed filetypes');
122 filter
.extension
= '';
123 for(var i
:Number = 0; i
<exts
.length
; i
++){
124 filter
.extension
+= '*.'+exts
[i
]+';';
126 filter
.extension
= filter
.extension
.substr
(0,filter
.extension
.length
-1);
127 var apply
:Array = new Array();
129 fileRef
.browse
(apply
);
136 * Initiates the upload process
138 private function upload
() {
139 // prepare backend URL
140 this.url
= _root
.O_backend
; // from flashvars
141 this.url
+= '&ns='+escape
(ns_input
.text
);
143 // prepare upload url
144 this.upurl
= this.url
;
145 this.upurl
+= '§ok='+escape
(_root
.O_sectok
);
146 this.upurl
+= '&authtok='+escape
(_root
.O_authtok
);
147 if(overwrite_cb
.selected
) this.upurl
+= '&ow=1';
150 upload_btn
.enabled
= false;
151 browse_btn
.enabled
= false;
152 ns_input
.enabled
= false;
153 overwrite_cb
.enabled
= false;
160 // start process detached
161 _global
.setTimeout
(this,'uploadNext',100);
166 * Uploads the next file in the list
168 private function uploadNext
(){
170 if(this.current
>= this.list
.length
){
171 return this.uploadDone
();
174 var file
= this.list
[this.current
];
176 if(_root
.O_maxsize
&& (file
.size
> _root
.O_maxsize
)){
177 this.lasterror
= (_root
.L_toobig
? _root
.L_toobig
: 'too big');
178 _global
.setTimeout
(this,'uploadNext',100);
181 file
.addListener
(fileRefListener
);
183 // continues in the handlers
188 * Redirect to the namespace and set a success/error message
190 * Called when all files in the list where processed
192 private function uploadDone
(){
193 var info
= (_root
.L_info
? _root
.L_info
: 'files uploaded');
194 if(this.done
== this.list
.length
){
195 this.url
+= '&msg1='+escape
(this.done
+'/'+this.list
.length
+' '+info
);
197 var lasterr
= (_root
.L_lasterr
? _root
.L_lasterr
: 'Last error:');
198 this.url
+= '&err='+escape
(this.done
+'/'+this.list
.length
+' '+info
+' '+lasterr
+' '+this.lasterror
);
201 // when done redirect
202 getURL
(this.url
,'_self');
206 * Set the status of a given file in the data grid
208 private function setStatus
(file
,msg
){
209 for(var i
:Number = 0; i
< list
.length
; i
++) {
210 if (list
[i
].name
== file
.name
) {
211 files_dg
.editField
(i
, 'status', msg
);
219 * Initialize the file reference listener
221 private function inifileRefListener
() {
222 fileRefListener
.onSelect
= Delegate
.create
(this, this.onSelect
);
223 fileRefListener
.onCancel
= Delegate
.create
(this, this.onCancel
);
224 fileRefListener
.onOpen
= Delegate
.create
(this, this.onOpen
);
225 fileRefListener
.onProgress
= Delegate
.create
(this, this.onProgress
);
226 fileRefListener
.onComplete
= Delegate
.create
(this, this.onComplete
);
227 fileRefListener
.onHTTPError
= Delegate
.create
(this, this.onHTTPError
);
228 fileRefListener
.onIOError
= Delegate
.create
(this, this.onIOError
);
229 fileRefListener
.onSecurityError
= Delegate
.create
(this, this.onSecurityError
);
233 * Handle file selection
235 * Files are added as in a list of references and beautified into the data grid dataprovider array
237 * Multiple browses will add to the list
239 private function onSelect
(fileRefList
:FileReferenceList) {
240 var sel
= fileRefList
.fileList
;
241 for(var i
:Number = 0; i
< sel
.length
; i
++) {
244 if(_root
.O_maxsize
&& sel
[i
].size
> _root
.O_maxsize
){
245 stat
= (_root
.L_toobig
? _root
.L_toobig
: 'too big');
247 stat
= (_root
.L_ready
? _root
.L_ready
: 'ready for upload');
250 dp
.push
({name
:sel
[i
].name
, size
:Math.round
(sel
[i
].size
/ 1000) + " kb", status
:stat
});
251 // add to reference list
255 files_dg
.dataProvider
= dp
;
256 files_dg
.spaceColumnsEqually
();
258 if(list
.length
> 0) upload_btn
.enabled
= true;
264 private function onCancel
() {
270 private function onOpen
(file
:FileReference) {
274 * Set the upload progress
276 private function onProgress
(file
:FileReference, bytesLoaded
:Number, bytesTotal
:Number) {
277 var percentDone
= Math.round
((bytesLoaded
/ bytesTotal
) * 100);
278 var msg
:String = 'uploading @PCT@%';
279 if(_root
.L_progress
) msg
= _root
.L_progress
;
280 msg
= msg
.split
('@PCT@').join
(percentDone
);
281 this.setStatus
(file
,msg
);
285 * Handle upload completion
287 private function onComplete
(file
:FileReference) {
288 this.setStatus
(file
,(_root
.L_done
? _root
.L_done
: 'complete'));
294 * Handle upload errors
296 private function onHTTPError
(file
:FileReference, httpError
:Number) {
298 if(httpError
== 400){
299 error
= (_root
.L_fail
? _root
.L_fail
: 'failed');
300 }else if(httpError
== 401){
301 error
= (_root
.L_authfail
? _root
.L_authfail
: 'auth failed');
303 error
= "HTTP Error " + httpError
305 this.setStatus
(file
,error
);
306 this.lasterror
= error
;
313 private function onIOError
(file
:FileReference) {
314 this.setStatus
(file
,"IO Error");
315 this.lasterror
= "IO Error";
320 * Handle Security errors
322 private function onSecurityError
(file
:FileReference, errorString
:String) {
323 this.setStatus
(file
,"SecurityError: " + errorString
);
324 this.lasterror
= "SecurityError: " + errorString
;