【发布时间】:2018-05-09 12:00:19
【问题描述】:
我正在开发一个代码库,我需要允许用户下载已经存在于 AWS S3 上的 PDF 文档。我已经实现了一个用于先前功能的下载问题。
对于此功能,我需要在用户完成文件下载后更新 UI(进度步进器)。我最初认为这很简单:
- 用户点击下载
- 在使用
send_data下载文件的地方进行API 调用。在此 API 调用中,我还将更新Foo模型以更改状态以指示用户已下载文件; - 执行
redirect_to request.referer以重新加载数据。Foo中的更改状态将负责在 UI 中显示更新的进度;
我错误地认为这会很简单。复杂的原因:
-
send_data已经在渲染数据,所以我无法使用redirect_to刷新页面,因为这会触发多次渲染错误; -
send_data不适用于remote: true选项,因此通过 AJAX 链接请求数据并更新 ERB 模板已失效; - 我可以将所有内容都写入一个 JS
on click函数,但这看起来有点像 hack。我可能需要直接从 AWS 检索文件并跳过我的 api?我怀疑我可能会遇到 CORS 问题,因为我无法控制服务器。
这是我的 rails 下载方法目前的样子:
def download
attachment = Attachment.find_by_id(params[:attachment_id])
content = send_data(
attachment.file.read,
filename: "#{attachment.title}.#{attachment.file.file.extension}",
type: attachment.content_type,
disposition: "attachment",
)
end
基本工作的 js 代码看起来像这样,其中所有相关的路径和文件名都通过数据属性传递给 JS:
$(document).on("click", "#download", function(e){
e.preventDefault();
const data = $('#temp-information').data();
var req = new XMLHttpRequest();
req.open("GET", data.path, true);
req.responseType = "blob";
const filename = data.title;
req.onload = function (event) {
var blob = req.response;
console.log(blob.size);
var link=document.createElement('a');
link.href=window.URL.createObjectURL(blob);
link.download= filename;
document.body.appendChild(link);
link.click();
};
if (typeof window.navigator.msSaveBlob !== 'undefined') {
// Fix to work in IE11
window.navigator.msSaveBlob(blob, filename);
} else {
req.send();
}
});
在下载完成后处理文件下载和更新 UI 的最有效和最有效的方式是什么?
【问题讨论】:
标签: javascript ruby-on-rails ruby-on-rails-4 download