我在我的网站上添加了通过Dropbox Chooser上传文件到我的网站的功能。除了一个问题,一切都正常 - 我不知道如何正确实现“取消”功能。它应该按照以下方式工作 - 当您单击“取消”时 - 相应的文件面板应从UI中删除,并停止从Dropbox上传。
当用户单击“从Dropbox选择”并选择文件并单击“提交”时,我会向Rails发起Ajax请求,调用方法“add_file_via_dropbox”。在这个方法中,我获取要通过“Paperclip” gem上传到“Amazon S3”服务器的Dropbox文件的URL。
当用户单击“取消”时,我想摆脱部分上传到S3的文件,该文件将存储(上传成功后)在“content.attachment”属性中。但是,当他单击“取消”时 - 文件仍在上传(否则他将看不到“取消”链接),我不知道如何立即删除它。
我的另一个想法是,我可以简单地向“内容”添加“已取消”的属性,然后不显示任何“内容”,其中这样的属性==“真”。“Amazon S3”的空间浪费,因此我应该每天运行一次后台任务以删除“已取消”的附件。我希望在第一时间不将它们保存在“Amazon S3”上。有可能吗?我考虑将控制器的操作“add_file_via_dropbox”移动到后台作业中,以便我能够在从客户端接收到“取消”ajax请求时立即“kill”它。我有点困惑所有这些。你会如何解决这个问题?谢谢。 product_form.html.erb
这段代码位于
因此,我将我的原始问题缩小到以下两个问题:
1)当文件正在下载到我的Rails服务器时,如何取消对
2)当文件从我的Rails服务器上传到S3时,如何取消对
当用户单击“从Dropbox选择”并选择文件并单击“提交”时,我会向Rails发起Ajax请求,调用方法“add_file_via_dropbox”。在这个方法中,我获取要通过“Paperclip” gem上传到“Amazon S3”服务器的Dropbox文件的URL。
当用户单击“取消”时,我想摆脱部分上传到S3的文件,该文件将存储(上传成功后)在“content.attachment”属性中。但是,当他单击“取消”时 - 文件仍在上传(否则他将看不到“取消”链接),我不知道如何立即删除它。
我的另一个想法是,我可以简单地向“内容”添加“已取消”的属性,然后不显示任何“内容”,其中这样的属性==“真”。“Amazon S3”的空间浪费,因此我应该每天运行一次后台任务以删除“已取消”的附件。我希望在第一时间不将它们保存在“Amazon S3”上。有可能吗?我考虑将控制器的操作“add_file_via_dropbox”移动到后台作业中,以便我能够在从客户端接收到“取消”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
后来添加
我更详细地调查了Paperclip的工作原理:
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保存
方法:(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(style).write(file,write_options)
的调用?
Rails
或Amazon S3
。done_tmpl
是一个html
元素吗?还是在html
元素内的内容?谢谢分享。 - guest271314