How to cancel file upload on Amazon S3?

I added the ability to upload files from Dropbox to my site using Dropbox Chooser. Everything works fine, except for one - I don’t know how to correctly implement Cancel functionality. It should work this way - when you click Cancel - the corresponding file panel should be removed from the user interface, and downloading from Dropbox should stop.

When the user clicks Choose from Dropbox and selects the file and clicks Submit , I run an Ajax request to the Rails add_file_via_dropbox method. In this method, I get the URL for the Dropbox file to upload to the Amazon S3 server using Paperclip gem.

When the user clicks Cancel , I want to get rid of the partially downloaded S3 file, which will be saved (after successful loading) in the content.attachment attribute. But when he clicks Cancel , the file is still loading (otherwise he won’t see the Cancel link), and I don’t know how to delete it right away.

My other thought is that I can just add the cancelled attribute to content and then not show content where such attribute == true . But this approach will not save me from losing space on Amazon S3 , so I have to run some background tasks once a day to remove the cancelled attachments. I would prefer not to save them on S3 in the first place. Is it possible? I was thinking of moving the add_file_via_dropbox controller add_file_via_dropbox to a background job so that I can kill it as soon as I received the Cancel ajax request from the client. I am a little confused about all this. How would you solve this problem? Thanks.

http://i61.tinypic.com/am9p8n.png

product_form.html.erb

 $.ajax({ // Cancel file uploading on client side via jqXHR.abort() // It quite useless because with 99% probability that request // already was sent to Rails and is processing by appropriate action beforeSend: function(jqXHR, options) { tmpl.find('a').click(function(e) { e.preventDefault(); jqXHR.abort(); $(this).parents('li').remove(); }); }, type: "POST", dataType: "json", url: "<%= add_file_via_dropbox_url %>", data: { product_id: $("#fileupload").data("product_id"), file: dropbox_file }, }) // When Rails response is returned - update UI with "successful upload state" .done(function(json_file) { var done_tmpl = $(tmpl("template-download", json_file)); var li = $(".files_list").find('[data-uuid="' + json_file.uuid + '"]'); li.replaceWith(done_tmpl); } }) 

product_controller.rb

 # This method is called by Ajax request def add_file_via_dropbox product = Product.find(params[:product_id]) # Each Product has_many Contents(files) file = params[:file] content = product.contents.build content.attachment_remote_url = file[:url] content.save # Construct json response object for Ajax call json_obj = [] json_obj << {name: content.attachment_file_name, size: content.attachment_file_size, url: content.attachment.url, thumbnailUrl: content.attachment.url, deleteUrl: "#{root_url}profile/products/delete_content/#{product.id}/#{content.id}", deleteType: "DELETE", uuid: file[:uuid]} respond_to do |format| format.json { render json: json_obj } end end 

content.rb

 class Content attr_reader :attachment_remote_url has_attached_file :attachment, bucket: ENV['S3_BUCKET_NAME'] def attachment_remote_url=(url_value) self.attachment = URI.parse(url_value) end end 

ADD AFTER

I examined in more detail how Paperclip works:

1) When this line of code executes

 content.attachment_remote_url = file[:url] 

This clip code is executed from paperclip/.../uri_adapter.rb Which file is downloaded from the given URL (Dropbox URL in my example) and saves it locally (in a temporary file on the Rails server)

 class UriAdapter < AbstractAdapter def initialize(target) @target = target @content = download_content # <---- cache_current_values @tempfile = copy_to_tempfile(@content) end ... def download_content open(@target) # method from 'open-uri' library end 

2) This file will be transferred to S3 only when saving my model here:

 content.attachment_remote_url = file[:url] content.save # <---- 

The Paperclip save method is called: ( paperclip/.../attachment.rb )

 def save flush_deletes unless @options[:keep_old_files] flush_writes # <----- @dirty = false true end 

And flush_writes then pushes the local file to S3 ( paperclip/.../s3.rb )

 def flush_writes # omitted code s3_object(style).write(file, write_options) # method from `aws-sdk` gem # omitted code end 

Therefore, I will judge my initial question by the following two:

1) How to cancel a call to open(@target) when it is already in action (the file is uploaded to my Rails server)

2) How to cancel the call to s3_object(style).write(file, write_options) when the file is downloaded from my Rails server to S3?

+8
jquery ajax ruby-on-rails amazon-s3 paperclip
source share
1 answer

If the file is still uploaded to the server before the server processes the file on S3, you want to end the connection, just like you. That is, how to cancel / abort jQuery AJAX request?

If the file is uploaded to the server and now uploads to S3: since ruby ​​is not based on asynchronous mode, you will essentially need to upload the file, but since the server is now downloading it, your client can technically leave the page. So: I would pass in a unique identifier when your server receives the file, if the user still clicked the Cancel button, then run the identifier and check your server’s poll or, i.e. Cron to delete a file.

+2
source share

All Articles