如何在客户端而不是在表单提交上触发文件上传?

Bla*_*man 4 ruby-on-rails amazon-s3 rails-activestorage

我有一个使用 s3 的活动存储示例的工作版本,可在此处找到:

https://edgeguides.rubyonrails.org/active_storage_overview.html

现在我希望能够在完成填写表单后而不是在用户选择要上传的文件后立即执行文件上传。其实在我的情况我有有一个所见即所得的编辑器上跌落事件触发

var myCodeMirror = CodeMirror.fromTextArea(post_body, {
   lineNumbers: true,
   dragDrop: true
  });

  myCodeMirror.on('drop', function(data, e) {
    var file;
    var files;
    // Check if files were dropped
    files = e.dataTransfer.files;
    if (files.length > 0) {
      e.preventDefault();
      e.stopPropagation();
      file = files[0];
      console.log('File: ' + file.name);
      console.log('File: ' + file.type);
      return false;
    }
  });
Run Code Online (Sandbox Code Playgroud)

那么在那里,因为文件删除触发了这个事件,让我以某种方式将它发送到 active-storage 以便它立即开始将文件上传到 S3?

Car*_*III 6

从客户端触发上传

Active Storage 公开了DirectUploadJavaScript 类,您可以使用它直接从客户端触发文件上传。

您可以利用它与第三方插件(例如 Uppy、Dropzone)或您自己的自定义 JS 代码集成。

使用 DirectUpload

您需要做的第一件事是确保将 AWS S3 设置为处理直接上传。这需要确保您的 CORS 配置设置正确。

接下来,您只需实例化DirectUpload类的一个实例,将要上传的文件和上传 URL 传递给它。

import { DirectUpload } from "activestorage"

// your form needs the file_field direct_upload: true, which
// provides data-direct-upload-url
const input = document.querySelector('input[type=file]')
const url = input.dataset.directUploadUrl
const upload = new DirectUpload(file, url)

upload.create((error, blob) => { 
   // handle errors OR persist to the model using 'blob.signed_id'
})
Run Code Online (Sandbox Code Playgroud)

在此处查看完整文档:https : //edgeguides.rubyonrails.org/active_storage_overview.html#integrating-with-libraries-or-frameworks

DirectUpload#create方法启动到 S3 的上传并返回错误或上传的文件 blob。

假设没有错误,最后一步是将上传的文件持久化到模型中。您可以使用blob.signed_id并将其放入页面上某处的隐藏字段或使用 AJAX 请求来更新您的模型。

上传文件

在上面的例子中,要在 drop 上开始直接上传,只需将上面的代码放入drop处理程序中。

像这样的东西:

myCodeMirror.on('drop', function(data, e) {
   // Get the file
   var file = e.dataTransfer.files[0];

   // You need a file input somewhere on the page...
   const input = document.querySelector('input[type=file]')
   const url = input.dataset.directUploadUrl

   // Instantiate the DirectUploader object
   const upload = new DirectUpload(file, url)

   // Upload the file
   upload.create((error, blob) => { ... })
});
Run Code Online (Sandbox Code Playgroud)

使用资产管道

如果您只是使用资产管道而不使用 JavaScript 打包工具,那么您可以DirectUpload像这样创建类的实例

const upload = new ActiveStorage.DirectUpload(file, url)

  • 现在是 `import { DirectUpload } from "@rails/activestorage"` (2认同)