larsklevan_s3_swf_upload 0.3.2
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +6 -0
- data/CHANGELOG +26 -0
- data/Gemfile +4 -0
- data/MIT-LICENSE +20 -0
- data/Manifest +34 -0
- data/README.textile +222 -0
- data/Rakefile +14 -0
- data/flex_src/bin-release/flex-config.xml +356 -0
- data/flex_src/compile +2 -0
- data/flex_src/src/Globals.as +15 -0
- data/flex_src/src/S3Uploader.as +204 -0
- data/flex_src/src/com/adobe/net/MimeTypeMap.as +196 -0
- data/flex_src/src/com/elctech/S3UploadOptions.as +31 -0
- data/flex_src/src/com/elctech/S3UploadRequest.as +254 -0
- data/flex_src/src/com/nathancolgate/s3_swf_upload/BrowseButton.as +55 -0
- data/flex_src/src/com/nathancolgate/s3_swf_upload/S3Queue.as +117 -0
- data/flex_src/src/com/nathancolgate/s3_swf_upload/S3Signature.as +116 -0
- data/flex_src/src/com/nathancolgate/s3_swf_upload/S3Upload.as +111 -0
- data/lib/patch/integer.rb +12 -0
- data/lib/s3_swf_upload.rb +10 -0
- data/lib/s3_swf_upload/railtie.rb +16 -0
- data/lib/s3_swf_upload/railties/generators/s3_swf_upload.rb +19 -0
- data/lib/s3_swf_upload/railties/generators/uploader/USAGE +10 -0
- data/lib/s3_swf_upload/railties/generators/uploader/templates/amazon_s3.yml +20 -0
- data/lib/s3_swf_upload/railties/generators/uploader/templates/s3_down_button.gif +0 -0
- data/lib/s3_swf_upload/railties/generators/uploader/templates/s3_over_button.gif +0 -0
- data/lib/s3_swf_upload/railties/generators/uploader/templates/s3_up_button.gif +0 -0
- data/lib/s3_swf_upload/railties/generators/uploader/templates/s3_upload.js +118 -0
- data/lib/s3_swf_upload/railties/generators/uploader/templates/s3_upload.swf +0 -0
- data/lib/s3_swf_upload/railties/generators/uploader/templates/s3_uploads_controller.rb +53 -0
- data/lib/s3_swf_upload/railties/generators/uploader/uploader_generator.rb +20 -0
- data/lib/s3_swf_upload/railties/tasks/crossdomain.xml +5 -0
- data/lib/s3_swf_upload/s3_config.rb +43 -0
- data/lib/s3_swf_upload/signature.rb +203 -0
- data/lib/s3_swf_upload/view_helpers.rb +171 -0
- data/s3_swf_upload.gemspec +28 -0
- metadata +106 -0
@@ -0,0 +1,254 @@
|
|
1
|
+
package com.elctech {
|
2
|
+
|
3
|
+
// import flash.events.*;
|
4
|
+
import flash.events.EventDispatcher;
|
5
|
+
import flash.events.ProgressEvent;
|
6
|
+
import flash.events.Event;
|
7
|
+
import flash.events.IOErrorEvent;
|
8
|
+
import flash.events.SecurityErrorEvent;
|
9
|
+
import flash.events.HTTPStatusEvent;
|
10
|
+
import flash.events.DataEvent;
|
11
|
+
|
12
|
+
// import flash.net.*;
|
13
|
+
import flash.net.FileReference;
|
14
|
+
import flash.net.URLVariables;
|
15
|
+
import flash.net.URLRequest;
|
16
|
+
import flash.net.URLRequestMethod;
|
17
|
+
|
18
|
+
import flash.system.Security;
|
19
|
+
import flash.xml.XMLDocument;
|
20
|
+
import flash.xml.XMLNode;
|
21
|
+
// import mx.controls.Alert;
|
22
|
+
|
23
|
+
/**
|
24
|
+
* This class encapsulates a POST request to S3.
|
25
|
+
*
|
26
|
+
* After you create an S3PostRequest, invoke S3PostRequest::upload(fileReference:FileReference).
|
27
|
+
*
|
28
|
+
*/
|
29
|
+
public class S3UploadRequest extends EventDispatcher {
|
30
|
+
|
31
|
+
[Event(name="open", type="flash.events.Event.OPEN")]
|
32
|
+
[Event(name="uploadCompleteData", type="flash.events.DataEvent.UPLOAD_COMPLETE_DATA")]
|
33
|
+
[Event(name="ioError", type="flash.events.IOErrorEvent.IO_ERROR")]
|
34
|
+
[Event(name="securityError", type="flash.events.SecurityErrorEvent.SECURITY_ERROR")]
|
35
|
+
[Event(name="progress", type="flash.events.ProgressEvent.PROGRESS")]
|
36
|
+
|
37
|
+
private var _accessKeyId:String;
|
38
|
+
private var _bucket:String;
|
39
|
+
private var _key:String;
|
40
|
+
private var _options:S3UploadOptions;
|
41
|
+
private var _httpStatusErrorReceived:Boolean;
|
42
|
+
private var _uploadStarted:Boolean;
|
43
|
+
private var fileReference:FileReference;
|
44
|
+
|
45
|
+
private const ENDPOINT:String = "s3.amazonaws.com";
|
46
|
+
private const MIN_BUCKET_LENGTH:int = 3;
|
47
|
+
private const MAX_BUCKET_LENGTH:int = 63;
|
48
|
+
|
49
|
+
|
50
|
+
/**
|
51
|
+
* Creates and initializes a new S3PostRequest object.
|
52
|
+
* @param accessKeyId The AWS access key id to authenticate the request
|
53
|
+
* @param bucket The bucket to POST into
|
54
|
+
* @param key The key to create
|
55
|
+
* @param options Options for this request
|
56
|
+
*/
|
57
|
+
public function S3UploadRequest(options:S3UploadOptions) {
|
58
|
+
|
59
|
+
_accessKeyId = options.AWSAccessKeyId;
|
60
|
+
_bucket = options.bucket;
|
61
|
+
_key = options.key;
|
62
|
+
_options = options;
|
63
|
+
}
|
64
|
+
|
65
|
+
private function buildUrl():String {
|
66
|
+
|
67
|
+
var canUseVanityStyle:Boolean = canUseVanityStyle(_bucket);
|
68
|
+
|
69
|
+
if(_options.Secure!="false" && canUseVanityStyle && _bucket.match(/\./)) {
|
70
|
+
// We cannot use SSL for bucket names containing "."
|
71
|
+
// The certificate won't match "my.bucket.s3.amazonaws.com"
|
72
|
+
throw new SecurityError("Cannot use SSL with bucket name containing '.': " + _bucket);
|
73
|
+
}
|
74
|
+
|
75
|
+
var postUrl:String = "http" + ((_options.Secure == 'true') ? "s" : "") + "://";
|
76
|
+
|
77
|
+
if(canUseVanityStyle) {
|
78
|
+
postUrl += _bucket + "." + ENDPOINT;
|
79
|
+
} else {
|
80
|
+
postUrl += ENDPOINT + "/" + _bucket;
|
81
|
+
}
|
82
|
+
|
83
|
+
return postUrl;
|
84
|
+
}
|
85
|
+
|
86
|
+
private function canUseVanityStyle(bucket:String):Boolean {
|
87
|
+
if( bucket.length < MIN_BUCKET_LENGTH ||
|
88
|
+
bucket.length > MAX_BUCKET_LENGTH ||
|
89
|
+
bucket.match(/^\./) ||
|
90
|
+
bucket.match(/\.$/) ) {
|
91
|
+
return false;
|
92
|
+
}
|
93
|
+
|
94
|
+
// must be lower case
|
95
|
+
if(bucket.toLowerCase() != bucket) {
|
96
|
+
return false;
|
97
|
+
}
|
98
|
+
|
99
|
+
// Check not IPv4-like
|
100
|
+
if (bucket.match(/^[0-9]|+\.[0-9]|+\.[0-9]|+\.[0-9]|+$/)) {
|
101
|
+
return false;
|
102
|
+
}
|
103
|
+
|
104
|
+
// Check each label
|
105
|
+
if(bucket.match(/\./)) {
|
106
|
+
var labels:Array = bucket.split(/\./);
|
107
|
+
for (var i:int = 0;i < labels.length; i++) {
|
108
|
+
if(!labels[i].match(/^[a-z0-9]([a-z0-9\-]*[a-z0-9])?$/)) {
|
109
|
+
return false;
|
110
|
+
}
|
111
|
+
}
|
112
|
+
}
|
113
|
+
|
114
|
+
return true;
|
115
|
+
}
|
116
|
+
|
117
|
+
private function loadPolicyFile(postUrl:String):void {
|
118
|
+
/*
|
119
|
+
* Due to the restrictions imposed by the Adobe Flash security sandbox,
|
120
|
+
* the bucket being uploaded to must contain a public-readable crossdomain.xml
|
121
|
+
* file that allows access from the domain that served the SWF hosting this code.
|
122
|
+
*
|
123
|
+
* Read Adobe's documentation on the Flash security sandbox for more information.
|
124
|
+
*
|
125
|
+
*/
|
126
|
+
|
127
|
+
Security.loadPolicyFile(postUrl + "/crossdomain.xml");
|
128
|
+
}
|
129
|
+
|
130
|
+
|
131
|
+
public function removeListeners():void {
|
132
|
+
trace('removeListeners');
|
133
|
+
fileReference.removeEventListener(Event.OPEN, onOpen);
|
134
|
+
fileReference.removeEventListener(ProgressEvent.PROGRESS, onProgress);
|
135
|
+
fileReference.removeEventListener(IOErrorEvent.IO_ERROR, onIOError);
|
136
|
+
fileReference.removeEventListener(SecurityErrorEvent.SECURITY_ERROR, onSecurityError);
|
137
|
+
fileReference.removeEventListener(DataEvent.UPLOAD_COMPLETE_DATA, onUploadCompleteData);
|
138
|
+
fileReference.removeEventListener(HTTPStatusEvent.HTTP_STATUS, onHttpStatus);
|
139
|
+
}
|
140
|
+
/**
|
141
|
+
* Initiates a POST upload request to S3
|
142
|
+
* @param fileReference A FileReference object referencing the file to upload to S3.
|
143
|
+
*/
|
144
|
+
public function upload(_fileReference:FileReference):void {
|
145
|
+
|
146
|
+
if(_uploadStarted) {
|
147
|
+
throw new Error("S3PostRequest object cannot be reused. Create another S3PostRequest object to send another request to Amazon S3.");
|
148
|
+
}
|
149
|
+
_uploadStarted = true;
|
150
|
+
|
151
|
+
// Save the FileReference object so that it doesn't get GCed.
|
152
|
+
// If this happens, we can lose events that should be dispatched.
|
153
|
+
fileReference = _fileReference;
|
154
|
+
|
155
|
+
var postUrl:String = buildUrl();
|
156
|
+
loadPolicyFile(postUrl);
|
157
|
+
var urlRequest:URLRequest = new URLRequest(postUrl);
|
158
|
+
urlRequest.method = URLRequestMethod.POST;
|
159
|
+
urlRequest.data = buildPostVariables();
|
160
|
+
|
161
|
+
// set up event handlers *****************************************************
|
162
|
+
fileReference.addEventListener(Event.OPEN, onOpen);
|
163
|
+
fileReference.addEventListener(ProgressEvent.PROGRESS, onProgress);
|
164
|
+
fileReference.addEventListener(IOErrorEvent.IO_ERROR, onIOError);
|
165
|
+
fileReference.addEventListener(SecurityErrorEvent.SECURITY_ERROR, onSecurityError);
|
166
|
+
fileReference.addEventListener(DataEvent.UPLOAD_COMPLETE_DATA, onUploadCompleteData);
|
167
|
+
fileReference.addEventListener(HTTPStatusEvent.HTTP_STATUS, onHttpStatus);
|
168
|
+
// *****************************************************************************
|
169
|
+
|
170
|
+
// send the request
|
171
|
+
fileReference.upload(urlRequest, "file", false);
|
172
|
+
}
|
173
|
+
|
174
|
+
private function buildPostVariables():URLVariables {
|
175
|
+
|
176
|
+
var postVariables:URLVariables = new URLVariables();
|
177
|
+
|
178
|
+
postVariables.key = _key;
|
179
|
+
postVariables.acl = _options.acl;
|
180
|
+
postVariables.AWSAccessKeyId = _accessKeyId;
|
181
|
+
postVariables.signature = _options.signature;
|
182
|
+
postVariables["Content-Type"] = _options.ContentType;
|
183
|
+
postVariables["Content-Disposition"] = "attachment";
|
184
|
+
postVariables.policy = _options.policy;
|
185
|
+
|
186
|
+
/**
|
187
|
+
* Certain combinations of Flash player version and platform don't handle
|
188
|
+
* HTTP responses with the header 'Content-Length: 0'. These clients do not
|
189
|
+
* dispatch completion or error events when such a response is received.
|
190
|
+
* Therefore it is impossible to tell when the upload has completed or failed.
|
191
|
+
*
|
192
|
+
* Flash clients should always set the success_action_status parameter to 201
|
193
|
+
* so that Amazon S3 returns a response with Content-Length being non-zero.
|
194
|
+
*
|
195
|
+
*/
|
196
|
+
postVariables.success_action_status = "201";
|
197
|
+
|
198
|
+
return postVariables;
|
199
|
+
}
|
200
|
+
|
201
|
+
private function onOpen(event:Event):void {
|
202
|
+
trace('onOpen: '+this._key);
|
203
|
+
this.dispatchEvent(event);
|
204
|
+
}
|
205
|
+
private function onIOError(event:IOErrorEvent):void {
|
206
|
+
/*
|
207
|
+
* FileReference.upload likes to send cryptic IOErrors when it doesn't get a status code that it likes.
|
208
|
+
* If we already got an error HTTP status code, don't propagate this event since the HTTPStatusEvent
|
209
|
+
* event handler dispatches an IOErrorEvent.
|
210
|
+
*/
|
211
|
+
if(!_httpStatusErrorReceived) {
|
212
|
+
this.dispatchEvent(event);
|
213
|
+
}
|
214
|
+
}
|
215
|
+
private function onSecurityError(event:SecurityErrorEvent):void {
|
216
|
+
this.dispatchEvent(event);
|
217
|
+
}
|
218
|
+
private function onProgress(event:ProgressEvent):void {
|
219
|
+
this.dispatchEvent(event);
|
220
|
+
}
|
221
|
+
private function onUploadCompleteData(event:DataEvent):void {
|
222
|
+
var data:String = event.data;
|
223
|
+
if(isError(data)) {
|
224
|
+
this.dispatchEvent(
|
225
|
+
new IOErrorEvent(IOErrorEvent.IO_ERROR, event.bubbles, event.cancelable, "Amazon S3 returned an error: " + data + ".")
|
226
|
+
);
|
227
|
+
} else {
|
228
|
+
this.dispatchEvent(new DataEvent(DataEvent.UPLOAD_COMPLETE_DATA, event.bubbles, event.cancelable, data));
|
229
|
+
}
|
230
|
+
}
|
231
|
+
private function onHttpStatus(event:HTTPStatusEvent):void {
|
232
|
+
_httpStatusErrorReceived = true;
|
233
|
+
if(Math.floor(event.status/100) == 2) {
|
234
|
+
this.dispatchEvent(new DataEvent(DataEvent.UPLOAD_COMPLETE_DATA, event.bubbles, event.cancelable, "Amazon S3 returned HTTP status " + event.status.toString() + "."));
|
235
|
+
} else {
|
236
|
+
this.dispatchEvent(new IOErrorEvent(IOErrorEvent.IO_ERROR, event.bubbles, event.cancelable, "Amazon S3 returned an error: HTTP status " + event.status.toString() + "."));
|
237
|
+
}
|
238
|
+
}
|
239
|
+
|
240
|
+
private function isError(responseText:String):Boolean {
|
241
|
+
var xml:XMLDocument = new XMLDocument();
|
242
|
+
xml.ignoreWhite = true;
|
243
|
+
xml.parseXML(responseText);
|
244
|
+
var root:XMLNode = xml.firstChild;
|
245
|
+
if( root == null || root.nodeName != "Error" )
|
246
|
+
{
|
247
|
+
return false;
|
248
|
+
}
|
249
|
+
return true;
|
250
|
+
}
|
251
|
+
|
252
|
+
}
|
253
|
+
|
254
|
+
}
|
@@ -0,0 +1,55 @@
|
|
1
|
+
package com.nathancolgate.s3_swf_upload {
|
2
|
+
|
3
|
+
import flash.display.*;
|
4
|
+
import flash.events.MouseEvent;
|
5
|
+
import flash.events.Event;
|
6
|
+
import flash.net.*;
|
7
|
+
|
8
|
+
public dynamic class BrowseButton extends Sprite {
|
9
|
+
|
10
|
+
private var _playButton:flash.display.SimpleButton;
|
11
|
+
|
12
|
+
public function BrowseButton(width:Number,
|
13
|
+
height:Number,
|
14
|
+
buttonUpUrl:String,
|
15
|
+
buttonDownUrl:String,
|
16
|
+
buttonOverUrl:String)
|
17
|
+
{
|
18
|
+
super();
|
19
|
+
|
20
|
+
_playButton = new flash.display.SimpleButton();
|
21
|
+
_playButton.useHandCursor = true;
|
22
|
+
addChild(_playButton);
|
23
|
+
|
24
|
+
// Hit Test
|
25
|
+
var hit_test:Shape = new flash.display.Shape();
|
26
|
+
hit_test.graphics.beginFill(0xFFCC00);
|
27
|
+
hit_test.graphics.drawRect(0, 0, width, height);
|
28
|
+
hit_test.graphics.endFill();
|
29
|
+
_playButton.hitTestState = hit_test;
|
30
|
+
|
31
|
+
// Up
|
32
|
+
var upLoader:Loader = new Loader();
|
33
|
+
upLoader.contentLoaderInfo.addEventListener(Event.COMPLETE,function(e:Event):void{
|
34
|
+
_playButton.upState = new Bitmap(e.target.content.bitmapData);
|
35
|
+
});
|
36
|
+
upLoader.load(new URLRequest(buttonUpUrl));
|
37
|
+
|
38
|
+
// Down
|
39
|
+
var downLoader:Loader = new Loader();
|
40
|
+
downLoader.contentLoaderInfo.addEventListener(Event.COMPLETE,function(e:Event):void{
|
41
|
+
_playButton.downState = new Bitmap(e.target.content.bitmapData);
|
42
|
+
});
|
43
|
+
downLoader.load(new URLRequest(buttonDownUrl));
|
44
|
+
|
45
|
+
// Over
|
46
|
+
var overLoader:Loader = new Loader();
|
47
|
+
overLoader.contentLoaderInfo.addEventListener(Event.COMPLETE,function(e:Event):void{
|
48
|
+
_playButton.overState = new Bitmap(e.target.content.bitmapData);
|
49
|
+
});
|
50
|
+
overLoader.load(new URLRequest(buttonOverUrl));
|
51
|
+
}
|
52
|
+
|
53
|
+
|
54
|
+
}
|
55
|
+
}
|
@@ -0,0 +1,117 @@
|
|
1
|
+
package com.nathancolgate.s3_swf_upload {
|
2
|
+
|
3
|
+
import mx.collections.ArrayCollection;
|
4
|
+
import mx.events.CollectionEvent;
|
5
|
+
import flash.external.ExternalInterface;
|
6
|
+
import flash.net.FileReference;
|
7
|
+
import com.nathancolgate.s3_swf_upload.*;
|
8
|
+
|
9
|
+
public class S3Queue extends ArrayCollection {
|
10
|
+
|
11
|
+
// S3 Interaction Vars
|
12
|
+
private var _signatureUrl:String;
|
13
|
+
private var _prefixPath:String;
|
14
|
+
|
15
|
+
public var currentSignature:S3Signature;
|
16
|
+
|
17
|
+
public function S3Queue(signatureUrl:String,
|
18
|
+
prefixPath:String,
|
19
|
+
source:Array = null) {
|
20
|
+
|
21
|
+
_signatureUrl = signatureUrl;
|
22
|
+
_prefixPath = prefixPath;
|
23
|
+
super(source);
|
24
|
+
|
25
|
+
// Outgoing calls
|
26
|
+
this.addEventListener(CollectionEvent.COLLECTION_CHANGE, changeHandler);
|
27
|
+
// Incoming calls
|
28
|
+
ExternalInterface.addCallback("startUploading", startUploadingHandler);
|
29
|
+
ExternalInterface.addCallback("clearQueue", clearHandler);
|
30
|
+
ExternalInterface.addCallback("stopUploading", stopUploadingHandler);
|
31
|
+
}
|
32
|
+
|
33
|
+
public function uploadNextFile():void{
|
34
|
+
// ExternalInterface.call('s3_swf.jsLog','uploadNextFile');
|
35
|
+
// ExternalInterface.call('s3_swf.jsLog','Start uploadNextFile...');
|
36
|
+
var next_file:FileReference = FileReference(this.getItemAt(0));
|
37
|
+
currentSignature = new S3Signature(next_file,_signatureUrl,_prefixPath);
|
38
|
+
// ExternalInterface.call('s3_swf.jsLog','End uploadNextFile');
|
39
|
+
}
|
40
|
+
|
41
|
+
// whenever the queue changes this function is called
|
42
|
+
private function changeHandler(event:CollectionEvent):void{
|
43
|
+
// ExternalInterface.call('s3_swf.jsLog','changeHandler');
|
44
|
+
// ExternalInterface.call('s3_swf.jsLog','Calling onQueueChange...');
|
45
|
+
ExternalInterface.call(S3Uploader.s3_swf_obj+'.onQueueChange',this.toJavascript());
|
46
|
+
// ExternalInterface.call('s3_swf.jsLog','onQueueChange called');
|
47
|
+
}
|
48
|
+
|
49
|
+
// Remove all files from the upload queue;
|
50
|
+
private function clearHandler():void{
|
51
|
+
// ExternalInterface.call('s3_swf.jsLog','clearHandler');
|
52
|
+
// ExternalInterface.call('s3_swf.jsLog','Removing All...');
|
53
|
+
this.removeAll();
|
54
|
+
// ExternalInterface.call('s3_swf.jsLog','All removed');
|
55
|
+
// ExternalInterface.call('s3_swf.jsLog','Calling onQueueClear...');
|
56
|
+
ExternalInterface.call(S3Uploader.s3_swf_obj+'.onQueueClear',this.toJavascript());
|
57
|
+
// ExternalInterface.call('s3_swf.jsLog','onQueueClear called');
|
58
|
+
}
|
59
|
+
|
60
|
+
// Start uploading the files from the queue
|
61
|
+
private function startUploadingHandler():void{
|
62
|
+
// ExternalInterface.call('s3_swf.jsLog','startUploadingHandler');
|
63
|
+
if (this.length > 0){
|
64
|
+
// ExternalInterface.call('s3_swf.jsLog','Calling onUploadingStart...');
|
65
|
+
ExternalInterface.call(S3Uploader.s3_swf_obj+'.onUploadingStart');
|
66
|
+
// ExternalInterface.call('s3_swf.jsLog','onUploadingStart called');
|
67
|
+
// ExternalInterface.call('s3_swf.jsLog','Uploading next file...');
|
68
|
+
uploadNextFile();
|
69
|
+
// ExternalInterface.call('s3_swf.jsLog','Next file uploaded');
|
70
|
+
} else {
|
71
|
+
// ExternalInterface.call('s3_swf.jsLog','Calling onQueueEmpty...');
|
72
|
+
ExternalInterface.call(S3Uploader.s3_swf_obj+'.onQueueEmpty',this);
|
73
|
+
// ExternalInterface.call('s3_swf.jsLog','onQueueEmpty called');
|
74
|
+
}
|
75
|
+
}
|
76
|
+
|
77
|
+
// Cancel Current File Upload
|
78
|
+
// Which stops all future uploads as well
|
79
|
+
private function stopUploadingHandler():void{
|
80
|
+
// ExternalInterface.call('s3_swf.jsLog','stopUploadingHandler');
|
81
|
+
if (this.length > 0){
|
82
|
+
var current_file:FileReference = FileReference(this.getItemAt(0));
|
83
|
+
// ExternalInterface.call('s3_swf.jsLog','Cancelling current file...');
|
84
|
+
current_file.cancel();
|
85
|
+
|
86
|
+
currentSignature.s3upload.removeListeners();
|
87
|
+
|
88
|
+
// ExternalInterface.call('s3_swf.jsLog','Current file cancelled');
|
89
|
+
// ExternalInterface.call('s3_swf.jsLog','Calling onUploadingStop...');
|
90
|
+
ExternalInterface.call(S3Uploader.s3_swf_obj+'.onUploadingStop');
|
91
|
+
// ExternalInterface.call('s3_swf.jsLog','onUploadingStop called');
|
92
|
+
} else {
|
93
|
+
// ExternalInterface.call('s3_swf.jsLog','Calling onQueueEmpty...');
|
94
|
+
ExternalInterface.call(S3Uploader.s3_swf_obj+'.onQueueEmpty',this.toJavascript());
|
95
|
+
// ExternalInterface.call('s3_swf.jsLog','onQueueEmpty called');
|
96
|
+
}
|
97
|
+
}
|
98
|
+
|
99
|
+
// This is a rather silly function to need, especially since it worked at one point
|
100
|
+
// In flash player 10.1, you could no longer send files over external reference
|
101
|
+
// This is the hack to get around the problem. Essentially: turn all those
|
102
|
+
// Files into objects
|
103
|
+
// August 27, 2010 - NCC@BNB
|
104
|
+
public function toJavascript():Object {
|
105
|
+
var faux_queue:Object = new Object();
|
106
|
+
faux_queue.files = new Array();
|
107
|
+
for (var i:int = 0;i < source.length; i++) {
|
108
|
+
faux_queue.files[i] = new Object();
|
109
|
+
faux_queue.files[i].name = source[i].name;
|
110
|
+
faux_queue.files[i].size = source[i].size;
|
111
|
+
faux_queue.files[i].type = source[i].type;
|
112
|
+
}
|
113
|
+
return faux_queue;
|
114
|
+
}
|
115
|
+
|
116
|
+
}
|
117
|
+
}
|
@@ -0,0 +1,116 @@
|
|
1
|
+
package com.nathancolgate.s3_swf_upload {
|
2
|
+
|
3
|
+
import com.elctech.S3UploadOptions;
|
4
|
+
import com.nathancolgate.s3_swf_upload.*;
|
5
|
+
import flash.external.ExternalInterface;
|
6
|
+
import com.adobe.net.MimeTypeMap;
|
7
|
+
|
8
|
+
import flash.net.*
|
9
|
+
import flash.events.*
|
10
|
+
|
11
|
+
public class S3Signature {
|
12
|
+
|
13
|
+
private var upload_options:S3UploadOptions;
|
14
|
+
private var _file:FileReference;
|
15
|
+
|
16
|
+
public var s3upload:S3Upload;
|
17
|
+
|
18
|
+
public function S3Signature(file:FileReference,
|
19
|
+
signatureUrl:String,
|
20
|
+
prefixPath:String) {
|
21
|
+
_file = file;
|
22
|
+
|
23
|
+
// Create options list for file s3 upload metadata
|
24
|
+
upload_options = new S3UploadOptions;
|
25
|
+
upload_options.FileSize = _file.size.toString();
|
26
|
+
upload_options.FileName = getFileName(_file);
|
27
|
+
upload_options.ContentType = getContentType(upload_options.FileName);
|
28
|
+
upload_options.key = prefixPath + upload_options.FileName;
|
29
|
+
|
30
|
+
var variables:URLVariables = new URLVariables();
|
31
|
+
variables.key = upload_options.key
|
32
|
+
variables.content_type = upload_options.ContentType;
|
33
|
+
|
34
|
+
var request:URLRequest = new URLRequest(signatureUrl);
|
35
|
+
request.method = URLRequestMethod.GET;
|
36
|
+
request.data = variables;
|
37
|
+
|
38
|
+
var signature:URLLoader = new URLLoader();
|
39
|
+
signature.dataFormat = URLLoaderDataFormat.TEXT;
|
40
|
+
signature.addEventListener(Event.OPEN, openHandler);
|
41
|
+
signature.addEventListener(ProgressEvent.PROGRESS, progressHandler);
|
42
|
+
signature.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler);
|
43
|
+
signature.addEventListener(HTTPStatusEvent.HTTP_STATUS, httpStatusHandler);
|
44
|
+
signature.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
|
45
|
+
signature.addEventListener(Event.COMPLETE, completeHandler);
|
46
|
+
signature.load(request);
|
47
|
+
}
|
48
|
+
|
49
|
+
private function openHandler(event:Event):void {
|
50
|
+
ExternalInterface.call(S3Uploader.s3_swf_obj+'.onSignatureOpen',toJavascript(_file),event);
|
51
|
+
}
|
52
|
+
|
53
|
+
private function progressHandler(progress_event:ProgressEvent):void {
|
54
|
+
ExternalInterface.call(S3Uploader.s3_swf_obj+'.onSignatureProgress',toJavascript(_file),progress_event);
|
55
|
+
}
|
56
|
+
|
57
|
+
private function securityErrorHandler(security_error_event:SecurityErrorEvent):void {
|
58
|
+
ExternalInterface.call(S3Uploader.s3_swf_obj+'.onSignatureSecurityError',toJavascript(_file),security_error_event);
|
59
|
+
}
|
60
|
+
|
61
|
+
private function httpStatusHandler(http_status_event:HTTPStatusEvent):void {
|
62
|
+
ExternalInterface.call(S3Uploader.s3_swf_obj+'.onSignatureHttpStatus',toJavascript(_file),http_status_event);
|
63
|
+
}
|
64
|
+
|
65
|
+
private function ioErrorHandler(io_error_event:IOErrorEvent):void {
|
66
|
+
ExternalInterface.call(S3Uploader.s3_swf_obj+'.onSignatureIOError',toJavascript(_file),io_error_event);
|
67
|
+
}
|
68
|
+
|
69
|
+
private function completeHandler(event:Event):void {
|
70
|
+
ExternalInterface.call(S3Uploader.s3_swf_obj+'.onSignatureComplete',toJavascript(_file),event);
|
71
|
+
var loader:URLLoader = URLLoader(event.target);
|
72
|
+
var xml:XML = new XML(loader.data);
|
73
|
+
|
74
|
+
// create the s3 options object
|
75
|
+
upload_options.policy = xml.policy;
|
76
|
+
upload_options.signature = xml.signature;
|
77
|
+
upload_options.bucket = xml.bucket;
|
78
|
+
upload_options.AWSAccessKeyId = xml.accesskeyid;
|
79
|
+
upload_options.acl = xml.acl;
|
80
|
+
upload_options.Expires = xml.expirationdate;
|
81
|
+
upload_options.Secure = xml.https;
|
82
|
+
|
83
|
+
if (xml.errorMessage != "") {
|
84
|
+
ExternalInterface.call(S3Uploader.s3_swf_obj+'.onSignatureXMLError',toJavascript(_file),xml.errorMessage);
|
85
|
+
return;
|
86
|
+
}
|
87
|
+
|
88
|
+
s3upload = new S3Upload(upload_options);
|
89
|
+
}
|
90
|
+
|
91
|
+
/* MISC */
|
92
|
+
|
93
|
+
private function getContentType(fileName:String):String {
|
94
|
+
var fileNameArray:Array = fileName.split(/\./);
|
95
|
+
var fileExtension:String = fileNameArray[fileNameArray.length - 1];
|
96
|
+
var mimeMap:MimeTypeMap = new MimeTypeMap;
|
97
|
+
var contentType:String = mimeMap.getMimeType(fileExtension);
|
98
|
+
return contentType;
|
99
|
+
}
|
100
|
+
|
101
|
+
private function getFileName(file:FileReference):String {
|
102
|
+
var fileName:String = file.name.replace(/^.*(\\|\/)/gi, '').replace(/[^A-Za-z0-9\.\-]/gi, '_');
|
103
|
+
return fileName;
|
104
|
+
}
|
105
|
+
|
106
|
+
// Turns a FileReference into an Object so that ExternalInterface doesn't choke
|
107
|
+
private function toJavascript(file:FileReference):Object{
|
108
|
+
var javascriptable_file:Object = new Object();
|
109
|
+
javascriptable_file.name = file.name;
|
110
|
+
javascriptable_file.size = file.size;
|
111
|
+
javascriptable_file.type = file.type;
|
112
|
+
return javascriptable_file;
|
113
|
+
}
|
114
|
+
|
115
|
+
}
|
116
|
+
}
|