Rails ActiveStorage:DirectUpload 回调
Posted
技术标签:
【中文标题】Rails ActiveStorage:DirectUpload 回调【英文标题】:Rails ActiveStorage: DirectUpload callbacks 【发布时间】:2018-11-05 23:25:25 【问题描述】:我在直接使用 ActiveStorage 的 DirectUpload 对象时遇到了一些问题。我正在遵循 RailsGuides 中的示例,但我一定遗漏了一些东西。这是我的问题的快速布局:
-
我正在努力实现的目标。
我已经尝试过。
我目前的问题是什么。
1。我想要完成的事情
使用 ActiveStroage,我试图让用户在一个简单的表单上选择多个文件,并在选择文件后自动启动直接上传。
这是与最终用户交互的表单:
_media_upload_form.html.erb
<%= form_with url: elements_upload_path, local: true, id: "upload-elements" do %>
<span class="btn btn-primary btn-file">
<%= form.file_field :images, multiple: true, direct_upload: true %>
Select File(s)
</span>
<% end %>
2。我已经尝试过的事情
要在用户选择文件后自动上传文件,我必须直接与 DirectUpload 对象交互。这个提示可以在ActiveStroage RailsGuides 上找到。我可以毫无问题地使用以下 JS 代码:
direct_uploads.js
import DirectUpload from "activestorage"
const input = document.querySelector('input[type=file]')
const onDrop = (event) =>
event.preventDefault()
const files = event.dataTransfer.files;
Array.from(files).forEach(file => uploadFile(file))
input.addEventListener('change', (event) =>
Array.from(input.files).forEach(file => uploadFile(file))
input.value = null
)
const uploadFile = (file)
const url = input.dataset.directUploadUrl
const upload = new DirectUpload(file, url)
upload.create((error, blob) =>
if (error)
// Handle the error
else
const hiddenField = document.createElement('input')
hiddenField.setAttribute("type", "hidden");
hiddenField.setAttribute("value", blob.signed_id);
hiddenField.name = input.name
document.querySelector('form').appendChild(hiddenField)
)
所以,我完成了一个目标。我有文件一被选择就上传。现在,我的下一个目标是访问事件,因此我知道上传何时完成、进度等。知道上传何时完成尤为重要,这样我就可以提交表单并创建对象并将其附加到上传的文件中。所以,使用这样的东西:
addEventListener("direct-upload:progress", event =>
// ...
)
不起作用,因为我直接访问 DirectUpload 对象。至少,到目前为止,这是我的经验。有点不明白为什么,我注意到ActiveStroage RailsGuides 中的一个细节(我最初忽略了)说您可以通过创建自己的 DirectUpload 上传类来绑定处理程序。因此,使用指南中提供的示例,我创建了以下内容:
my_uploader.js
import DirectUpload from "activestorage"
class MyUploader
constructor(file, url)
this.upload = new DirectUpload(this.file, this.url, this)
upload(file)
this.upload.create((error, blob) =>
if (error)
// Handle the error
else
const hiddenField = document.createElement('input')
hiddenField.setAttribute("type", "hidden");
hiddenField.setAttribute("value", blob.signed_id);
hiddenField.name = input.name
document.querySelector('form').appendChild(hiddenField)
)
directUploadWillStoreFileWithXHR(request)
request.upload.addEventListener("progress",
event => this.directUploadDidProgress(event))
directUploadDidProgress(event)
console.log("Upload has some progress ....")
// ... all ES6 export calls ...
direct_uploads.js
import DirectUpload from "activestorage"
import MyUploader from "my_uploader"
const input = document.querySelector('input[type=file]')
const onDrop = (event) =>
event.preventDefault()
const files = event.dataTransfer.files;
Array.from(files).forEach(file => uploadFile(file))
input.addEventListener('change', (event) =>
Array.from(input.files).forEach(file => uploadFile(file))
input.value = null
)
const uploadFile = (file)
const url = input.dataset.directUploadUrl
const upload = new MyUploader(file, url)
3。我目前的问题是什么
我认为我的问题是我遗漏了一些东西,也许是一步。正在调用 MyUploader 构造函数,但不再上传文件。只有构造函数被调用,就是这样。不再调用实际的上传过程。我不知道如何让自定义 MyUploader 继续上传过程,就像 DirectUpload 对象一样。
任何人都可以提供任何方向将不胜感激。
谢谢!
【问题讨论】:
【参考方案1】:离开我的项目一段时间后,我以崭新的眼光回来,我看到了答案。
DirectUpload
可以带三个参数,第三个是MyUploader
对象。
所以答案是这样的:
const my_uploader = new MyUploader(file, url)
const upload = new DirectUpload(file, url, my_uploader)
【讨论】:
第二行应该是const upload = new DirectUpload(file, url, my_uploader)
这很有帮助,因为从 Active Storage 指南一目了然【参考方案2】:
我认为您的初始代码的问题在于构造函数中的this.upload
与您的upload
函数具有相同的名称。
查看 Rails 源代码,它们使用的代码几乎与您在 direct_upload_controller.js
中的 MyUploader
类中使用的代码相同,但它们将该方法称为 start
。
【讨论】:
以上是关于Rails ActiveStorage:DirectUpload 回调的主要内容,如果未能解决你的问题,请参考以下文章
如何在 ActiveStorage (Rails 5.2) 中更新附件
使用 ActiveStorage 将 Cloudinary 图像附加到 Rails 模型
从 Rails 6 中删除 ActiveStorage 路由
Rails ActiveStorage:DirectUpload 回调