Uploading files in ruby on rails application seems trivial task using attachment_fu plugin but it become non-trivial when you need to display upload progress.Recently we had requirements from client to show the progress bar while uploading the image/video files. We could show the file upload progress only when we upload with flash. We found swfupload a reliable solution for this and decided to use it. We were using attachment_fu plugin for the attachment and there is no easier way to integrate it with swfupload. attachment_fu saves the files using the mime type of the file and when swfupload is used for uploading the file, it set mimetype of files to application/octet-stream. It become difficult to detect the difference between image/video or other formated files. So we come up with a solution which first convert the convert the file data in same format which is expected by attachment_fu plugin and later detect the mimetype of the file.
Conversion of file data to attachment_fu format
Using attachment_fu plugin we were expecting the file data in params[:ASSET_DATA] but with swfupload data was coming as params[:Filedata]. So we wrapped the Filedata from swfupload and put that in the desired format
data = {"uploaded_data" =>params[:Filedata]}
Setting mimetype of the file
Attachment_fu requires the mimetype to be set correctly before it will accept the files. Matt Aimonetti wrote mimetype-fu to help attachment_fu properly set the mimetype.
We override the uploaded_data of attachment_fu in our model object.
#override attachment_fu plugin def uploaded_data=(file_data) return nil if file_data.nil? || file_data.size == 0 self.filename = file_data.original_filename if respond_to?(:filename) extension = file_data.original_filename.slice(/.w+$/) # Map file extensions to mime types. Thanks to bug in Flash 8 # the content type is always set to application/octet-stream. mime = MIME::Types.type_for(self.filename)[0] self.content_type = mime.blank? ? file_data.content_type : mime.content_type #Custom name of the file self.filename = "xxxx_" + Digest::SHA1.hexdigest(Time.now.to_s) + extension if file_data.is_a?(StringIO) file_data.rewind self.temp_data = file_data.read else self.temp_path = file_data.path end #callback after attachment is uploaded after_attachment_uploaded end
Please let us know if you have any issues using above code or have any questions.