【问题标题】:direct upload using active storage in rails - input.dataset.directUploadUrl "undefined"使用 Rails 中的活动存储直接上传 - input.dataset.directUploadUrl "undefined"
【发布时间】:2020-11-10 09:19:15
【问题描述】:

使用 rails 6 并尝试将文件 using this drag and drop JS framework 上传到本地磁盘,但得到“Failed to load resource: the server responded with a status of 404 (Not Found)”。这是因为 url 变量没有被定义。

控制台错误:ActionController::RoutingError (No route matches [POST] "/undefined"

我已按照此处的所有步骤操作:https://edgeguides.rubyonrails.org/active_storage_overview.html

JS代码:

import { DirectUpload } from "@rails/activestorage"
function uploadFile(file) {

const input = document.querySelector('input[type=file]')
console.log(input)

  // your form needs the file_field direct_upload: true, which
  //  provides data-direct-upload-url
  const url = input.dataset.directUploadUrl <-- returns "undefined"
  console.log(url)
  const upload = new DirectUpload(file, url)

  upload.create((error, blob) => {
    if (error) {
      // Handle the error
    } else {
      // Add an appropriately-named hidden input to the form with a
      //  value of blob.signed_id so that the blob ids will be
      //  transmitted in the normal upload flow
      const hiddenField = document.createElement('input')
      hiddenField.setAttribute("type", "hidden");
      hiddenField.setAttribute("value", blob.signed_id);
      hiddenField.name = input.name
      document.querySelector('form').appendChild(hiddenField)
    }
  })

HTML:

    <div id="drop-area">
      <form class="my-form">
        <p>Upload multiple files with the file dialog or by dragging and dropping images onto the dashed region</p>
        <input type="file" id="fileElem" multiple accept="image/*" onchange="handleFiles(this.files)" data-direct-upload = "true">
        <label class="button" for="fileElem">Select some files</label>
      </form>
      <progress id="progress-bar" max=100 value=0></progress>
      <div id="gallery" /></div>
    </div>

        <%= javascript_pack_tag 'dropzone.js' %>

我想知道主动存储是否不喜欢没有像这样整齐地打包在嵌入式 ruby​​ 代码中的表单数据:

<%= form.file_field :attachments, multiple: true, direct_upload: true %>

方法二: 如果我尝试在不使用活动存储 DirectUpload 方法的情况下发送文件,则会收到“加载资源失败:服务器响应状态为 400(错误请求)”,控制台输出为 ActionController::ParameterMissing (param is missing or the value is empty: blob)

这是 JS 代码:

function uploadFile(file, i) {
  var url2 = 'rails/active_storage/direct_uploads'
  var xhr = new XMLHttpRequest()
  var formData = new FormData()
  xhr.open('POST', url2, true)
  xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest')

   //Update progress (can be used to show progress indicator)
  xhr.upload.addEventListener("progress", function(e) {
    updateProgress(i, (e.loaded * 100.0 / e.total) || 100)
  })

  xhr.addEventListener('readystatechange', function(e) {
    if (xhr.readyState == 4 && xhr.status == 200) {
      updateProgress(i, 100) // <- Add this
    }
    else if (xhr.readyState == 4 && xhr.status != 200) {
      // Error. Inform the user
    }
  })

  formData.append('upload_preset', 'ujpu6gyk')
  formData.append('file', file)
  xhr.send(formData)
}

在对使用什么 URL 进行了一些研究之后,'rails/active_storage/direct_uploads' 似乎越过了 404 消息,而是抛出了 400。我不敢相信仅将文件上传到本地磁盘就这么困难。请帮忙!

【问题讨论】:

    标签: javascript ruby-on-rails ruby rails-activestorage jrubyonrails


    【解决方案1】:

    所以我还没有完全加深对主动存储的理解,但我确实找到了一个可行的解决方案。在方法 1 中,我只是将返回“未定义”的 URL 手动更改为 'rails/active_storage/direct_uploads'

    JS 代码现在看起来像:

    function uploadFile(file) {
    
    // const input = document.querySelector('input[type=file]')
    // console.log(input)
    
      // your form needs the file_field direct_upload: true, which
      //  provides data-direct-upload-url
      const url = 'rails/active_storage/direct_uploads' //input.dataset.directUploadUrl 
      console.log(url)
      const upload = new DirectUpload(file, url)
    
      upload.create((error, blob) => {
        if (error) {
          // Handle the error
        } else {
          // Add an appropriately-named hidden input to the form with a
          //  value of blob.signed_id so that the blob ids will be
          //  transmitted in the normal upload flow
          const hiddenField = document.createElement('input')
          hiddenField.setAttribute("type", "hidden");
          hiddenField.setAttribute("value", blob.signed_id);
          hiddenField.name = input.name
          document.querySelector('form').appendChild(hiddenField)
        }
      })
    

    上传后,我可以像这样(在 Ruby 中)对文件进行 blob 操作,而无需将它们下载到临时目录:

    blob = ActiveStorage::Blob.first
            blob.open do |tempfile|
              puts tempfile.path  #do some processing
              puts blob.filename
            end
    

    【讨论】:

      【解决方案2】:

      当你使用 erb 助手时,我刚刚遇到了类似的问题

       <%= form.file_field :images, direct_upload: true %>
      

      生成的输入包含一个 data-direct-upload-url 像这样

      <input data-direct-upload-url="http://localhost:3000/rails/active_storage/direct_uploads" type="file" name="post[images]" id="post_images">
      

      在我的情况下,我已经在页面上输入了一些其他文件,因此默认查询从活动存储示例中选择

      const input = document.querySelector('input[type=file]')
      

      在没有直接上传 url 的情况下返回另一个输入,导致与您遇到的类似错误。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-09-01
        • 2020-03-29
        • 2019-03-12
        • 2020-12-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-01-03
        相关资源
        最近更新 更多