【问题标题】:Rails 7 view and direct upload image from browser clientRails 7 查看并直接从浏览器客户端上传图片
【发布时间】:2023-01-26 05:33:21
【问题描述】:

我已经很久没有使用 Rails 作为 Web 应用程序的前端了,我当然想使用最新的版本,但似乎已经发生了很多变化,我不知道哪个是最 Rails Way做它了。

我试过使用 JQuery 和 FileUpload 插件,但我们不再有 JQuery,我的意思是我试过添加它但是使用新的导入映射很麻烦(我知道这是我的问题如果我查找一些教程,我可以做到),但这似乎与 Rails 应用程序中 JS 的当前心态背道而驰。

然后我去检查了新的 Hotwire + Stimulus 但我什至不知道从哪里开始,但从我看到的一点点不知道是否会处理这种情况:我已经从我的S3 Bucket 那里得到了一个presigned_url,并且只有一个带有f.file_field 的表单,我想将这个文件从客户端浏览器直接上传到S3 并执行POST 请求,所以用户不要在等待上传完成时被阻塞

如果我错了请纠正我,但要触发 JS 函数,Rails Way 现在是使用 StimulusHTML Data Attributes,但我不确定我是否可以在此数据属性中传递文件。

查看其他教程,我开始认为最好的方法是使用 turbo_stream_tag 来包装我的表单,然后在提交表单时将点击此涡轮控制器,它将作为一个 ajax 请求,异步运行做一个帖子使用 Net:HTTP 甚至 s3 gem 本身请求,我只是不确定我是否可以访问该文件。

任何善良的灵魂来澄清这一点?感谢并抱歉发了这么长的帖子。

【问题讨论】:

    标签: ruby-on-rails ruby-on-rails-7 stimulusjs hotwire-rails


    【解决方案1】:

    如果你还没有,你可能想看看这个:https://edgeguides.rubyonrails.org/active_storage_overview.html#example

    这是一个带有导入映射的默认 Rails 7 设置的启动器。主要取自上面的示例链接并包含在 Stimulus 中。

    # config/importmap.rb
    pin "@hotwired/stimulus", to: "stimulus.min.js", preload: true
    pin "@hotwired/stimulus-loading", to: "stimulus-loading.js", preload: true
    pin_all_from "app/javascript/controllers", under: "controllers"
    
    pin "@rails/activestorage", to: "https://ga.jspm.io/npm:@rails/activestorage@7.0.2/app/assets/javascripts/activestorage.esm.js"
    
    <!-- inside your form -->
    <div data-controller="upload">
      <%= form.file_field :avatar, direct_upload: true,
        data: { upload_target: "input",
                action:        "change->upload#uploadFile" } %>
      <div data-upload-target="progress"></div>
    </div>
    

    一旦选择文件,这将开始上传。和涡轮它是非阻塞的。只要浏览器不刷新,它就会上传。

    // app/javascripts/controllers/upload_controller.js
    
    import { Controller } from "@hotwired/stimulus";
    import { DirectUpload } from "@rails/activestorage";
    
    export default class extends Controller {
      static targets = ["input", "progress"];
    
      uploadFile() {
        Array.from(this.inputTarget.files).forEach((file) => {
          const upload = new DirectUpload(
            file,
            this.inputTarget.dataset.directUploadUrl,
            this // callback directUploadWillStoreFileWithXHR(request)
          );
          upload.create((error, blob) => {
            if (error) {
              console.log(error);
            } else {
              this.createHiddenBlobInput(blob);
              // if you're not submitting the form after upload, you need to attach
              // uploaded blob to some model here and skip hidden input.
            }
          });
        });
      }
    
      // add blob id to be submitted with the form
      createHiddenBlobInput(blob) {
        const hiddenField = document.createElement("input");
        hiddenField.setAttribute("type", "hidden");
        hiddenField.setAttribute("value", blob.signed_id);
        hiddenField.name = this.inputTarget.name;
        this.element.appendChild(hiddenField);
      }
    
      directUploadWillStoreFileWithXHR(request) {
        request.upload.addEventListener("progress", (event) => {
          this.progressUpdate(event);
        });
      }
    
      progressUpdate(event) {
        const progress = (event.loaded / event.total) * 100;
        this.progressTarget.innerHTML = progress;
    
        // if you navigate away from the form, progress can still be displayed 
        // with something like this:
        // document.querySelector("#global-progress").innerHTML = progress;
      }
    }
    

    【讨论】:

    • 一直有问题,我现在可以让请求发生,但是我从 S3 得到 403,我注意到的一件事是这是在做一个 POST 请求,我相信这应该是一个 PUT 请求但不要在此 upload.create 方法中指定如何指定。我创建了这样的 url s3.bucket(ENV['S3_BUCKET']).object(upload_key)..presigned_url(:put,{ acl: 'public-read' }) 这是我得到的错误,也许只是 S3 配置? The request signature we calculated does not match the signature you provided. Check your key and signing method.
    • 也许设置一个常规表格以确保所有配置正确并且上传正常,然后继续直接上传。我没有太多地使用直接上传,但上传 url 不应该仍然来自 storage.yml 中配置的 ActiveStorage。
    猜你喜欢
    • 2015-01-25
    • 2016-09-23
    • 1970-01-01
    • 2013-07-09
    • 1970-01-01
    • 1970-01-01
    • 2015-09-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多