【发布时间】:2014-05-06 11:53:42
【问题描述】:
我添加了通过 Dropbox 选择器将文件从 Dropbox 上传到我的网站的功能。
一切正常,除了一件事——我不知道如何正确实现Cancel 功能。它应该以这种方式工作 - 当您单击 Cancel 时 - 应该从 UI 中删除相应的文件面板,并且应该停止从 Dropbox 上传。
当用户单击Choose from Dropbox 并选择文件并单击Submit 时,我向Rails 发起Ajax 请求,发送至方法add_file_via_dropbox。在这种方法中,我通过 Paperclip gem 的帮助将 Dropbox 文件上传到 Amazon S3 服务器的 URL。
当用户单击Cancel 时,我想删除部分上传到S3 的文件,该文件将存储(成功上传后)在content.attachment 属性中。但是当他点击Cancel - 一个文件仍在上传(否则他不会看到Cancel 链接),我不知道如何立即删除它。
我的另一个想法是,我可以简单地将cancelled 属性添加到content,然后不显示任何content,其中此类属性== true。但是这种方法不会让我免于在Amazon S3 上浪费空间,所以我应该每天运行一次后台任务来删除cancelled 附件。
我不希望首先将它们保存在S3 上。可能吗?我考虑过将控制器的操作add_file_via_dropbox 移动到后台作业,这样我就可以在收到来自客户端的cancel ajax 请求后立即kill 它。我对这一切有点困惑。你将如何解决这个问题?谢谢。
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
稍后添加
我更详细地研究了回形针的工作原理:
1) 当这行代码执行时
content.attachment_remote_url = file[:url]
此回形针代码从 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) 仅当我在此处保存模型时,此文件才会推送到 S3:
content.attachment_remote_url = file[:url]
content.save # <----
Paperclip save 方法将被调用:(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) 如何在调用 open(@target) 时取消调用(文件正在下载到我的 Rails 服务器)
2) 当文件从我的 Rails 服务器上传到 S3 时,如何取消对 s3_object(style).write(file, write_options) 的调用?
【问题讨论】:
-
没有试过
Rails,也没有Amazon S3。done_tmpl是htmlelement吗?或者,htmlelement中的内容?感谢分享 -
tmpl("template-download") 将展开为 HTML 代码块。
-
请看帖子。感谢分享。希望这会有所帮助
标签: jquery ruby-on-rails ajax amazon-s3 paperclip