I’m working on various projects and for one certain project this company wanted a file sharing website, like yousendit.com for example, but the site should be in-house. I proposed Amazon S3 for the storage of the files, otherwise the VPS will become very expensive. This file sharing website should also handle large files, so a reliable upload method is desired. SWFUpload is a well known Flash upload application. So the requirements are now complete: Ruby on Rails, Amazon S3 and SWFUpload.
First I created a config file to enter my Amazon S3 credentials. The credentials are dependent on the Ruby on Rails environment.
Created a controller and added the index method. The method reads the S3 settings from the config file and generates the fields required for SWFUpload and S3.
<%content_for:headdo%><linkhref="/stylesheets/swfupload.css"rel="stylesheet"type="text/css"/><%end%><script type="text/javascript"src="/javascripts/swfupload/swfupload.js"></script><script type="text/javascript"src="/javascripts/swfupload/swfupload.queue.js"></script><script type="text/javascript"src="/javascripts/swfupload/fileprogress.js"></script><script type="text/javascript"src="/javascripts/swfupload/handlers.js"></script><script type="text/javascript">varswfu;window.onload=function(){varsettings={flash_url:"/assets/swfupload.swf",upload_url:"<%=@upload_url%>",http_success:[200,201,204],// FOR AWSfile_size_limit:"2 GB",file_types:"*.*",file_types_description:"All Files",file_upload_limit:100,file_queue_limit:0,file_post_name:"file",// FOR AWScustom_settings:{progressTarget:"fsUploadProgress",cancelButtonId:"btnCancel"},debug:<%=ENV['RAILS_ENV']=='development'?'true':'false'%>,// Button settingsbutton_image_url:"/images/buttonUploadText.png",button_placeholder_id:"spanButtonPlaceHolder",button_width:61,button_height:22,// The event handler functions are defined in handlers.jsfile_queued_handler:fileQueued,file_queue_error_handler:fileQueueError,file_dialog_complete_handler:fileDialogComplete,upload_start_handler:uploadStart,upload_progress_handler:uploadProgress,upload_error_handler:uploadError,upload_success_handler:uploadSuccess,upload_complete_handler:uploadComplete,queue_complete_handler:queueComplete,// Queue plugin eventpost_params:<%=@post.to_json%>// FOR AWS};swfu=newSWFUpload(settings);};</script><divid="content"><formid="form"action="/upload/upload"method="post"enctype="multipart/form-data"><divclass="fieldset flash"id="fsUploadProgress"><spanclass="legend">Upload Queue</span></div><divid="divStatus">0 Files Uploaded</div><div><spanid="spanButtonPlaceHolder"></span><inputid="btnCancel"type="button"value="Cancel All Uploads"onclick="swfu.cancelQueue();"disabled="disabled"style="margin-left: 2px; font-size: 8pt; height: 29px;"/></div></form></div>
Upload the file crossdomain.xml to the root of your bucket. This is for Flash to upload to a different domain.
12345
<?xml version="1.0"?><!DOCTYPE cross-domain-policy SYSTEM "http://www.macromedia.com/xml/dtds/cross-domain-policy.dtd"><cross-domain-policy><allow-access-fromdomain="*"secure="false"/></cross-domain-policy>
Finally took the files from the SWFUpload simpledemo and placed them in the following directories:
swfupload.swf in public/assets/
fileprogress.js, handles.js, swfupload.js and swfupload.queue.js in public/javascripts/swfupload/
buttonUploadText.png in public/images/
Now SWFUpload should be working in your Ruby on Rails application.
Callback
For my application I needed a callback to let my application know there was a file successfully uploaded to the S3 bucket. To get this functionality I added a function to the controller and modified the handlers.js file.
functionuploadSuccess(file,serverData){// HERE: Send a notification upload has succeedednewAjax.Request('/share/upload_done?'+Object.toQueryString(file),{method:'get',asynchronous:false,onSuccess:function(){varprogress=newFileProgress(file,this.customSettings.progressTarget);progress.setStatus("Sending meta data.");}});// HERE: endtry{varprogress=newFileProgress(file,this.customSettings.progressTarget);progress.setComplete();progress.setStatus("Complete.");progress.toggleCancel(false);}catch(ex){this.debug(ex);}}
When SWFUpload is done uploading it uses the javascript callback to update the status of the form and to send a notification to the Ruby on Rails application.