一切正常,除了一件事 – 我不知道如何正确实现取消功能.它应该以这种方式工作 – 当您单击取消时 – 应从UI中删除相应的文件面板,并停止从DropBox上传.
当用户单击从DropBox中选择并选择文件并单击提交时,我向Rails发起Ajax请求,方法为add_file_via_dropBox.在这个方法中,我通过Paperclip gem的帮助将DropBox文件的URL上传到Amazon S3服务器.
当用户单击取消时,我想要删除部分上传到S3文件,该文件将在content.attachment属性中存储(成功上载后).但是当他点击取消时 – 文件仍在上传(否则他将看不到取消链接),我不知道如何立即删除它.
我的另一个想法是,我可以简单地将取消的属性添加到内容,然后不显示任何内容,其中这样的属性== true.但是这种方法不会让我免于在Amazon S3上浪费空间,所以我应该每天运行一些后台任务来删除已取消的附件.
我宁愿不首先将它们保存在S3上.可能吗?我想将控制器的动作add_file_via_dropBox移动到后台作业,所以我可以在收到客户端的取消ajax请求后立即将其删除.我对这一切有点困惑.你怎么解决这个问题?谢谢.
product_form.html.erb
$.ajax({ // Cancel file uploading on client side via jqXHR.abort() // It's 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
加上以后
我更详细地调查了Paperclip的工作原理:
1)当这行代码执行时
content.attachment_remote_url = file[:url]
此paperclip代码从paperclip /…/ uri_adapter.rb执行
哪个从给定的URL下载文件(在我的示例中为DropBox URL)并将其保存在本地(在Rails服务器的临时文件中)
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)仅当我在此处@R_463_301@时,此文件才会被推送到S3:
content.attachment_remote_url = file[:url] content.save # <----
将调用Paperclip保存方法:(paperclip /…/ attachment.rb)
def save flush_deletes unless @options[:keep_old_files] flush_writes # <----- @dirty = false true end
然后flush_writes将本地文件推送到S3(paperclip /…/s3.rb)
def flush_writes # omitted code s3_object(style).write(file,write_options) # method from `aws-sdk` gem # omitted code end
因此,我将原来的问题缩小到这两个:
1)当它已经在运行时(文件正在下载到我的Rails服务器),如何取消对open(@target)的调用
2)当文件从我的Rails服务器上传到S3时,如何取消对s3_object(样式).write(file,write_options)的调用?