【问题标题】:Rails 4: How to upload files with AJAXRails 4:如何使用 AJAX 上传文件
【发布时间】:2013-09-06 20:59:22
【问题描述】:

我想用 AJAX 上传文件。在过去,我通过使用神奇的jQuery form plugin 来实现这一点,并且效果很好。目前我正在构建一个 Rails 应用程序并尝试以“Rails 方式”做事,所以我正在使用 Form Helper 和回形针 gem 添加文件附件。

rails docs 警告表单助手不适用于 AJAX 文件上传:

不同于其他表单制作一个异步文件上传表单不像 就像为 form_for 提供 remote: true 一样简单。使用 Ajax 表单 序列化由在浏览器中运行的 JavaScript 完成,并且 因为 JavaScript 不能从你的硬盘读取文件 无法上传。最常见的解决方法是使用不可见的 用作表单提交目标的 iframe。

似乎没有现成的解决方案。所以我想知道最聪明的做法是什么。好像我有几个选择:

  1. 使用表单助手和 iframe 技巧。
  2. 使用表单助手 + 加载 jQuery 表单插件来提交文件(不确定这是否会与 Rails 的真实性令牌等配合使用)
  3. 使用表单助手 + 回形针 + [其他一些 gem] 来扩展它的功能以允许提交 AJAX 表单。

这三个似乎都是可能的。我对#3知之甚少,特别是[其他一些宝石]部分。我发现了两个类似的问题(thisthis),其中提到了 Pic-Upload 的一个分支 Uploadify,但它们都有 2 年的历史并处理 Rails 2 和 3(并且 Uploadify 多年来没有更新)。所以考虑到发生了多少变化,我认为这确实是一个全新的问题:

在 Rails 4 中使用 AJAX 上传文件的最佳方式是什么?

【问题讨论】:

  • 我认为这句话清楚地解释了为什么你总是“使用神奇的 jQuery 表单插件”;)
  • 关于在 Rails 的表单助手旁边使用它的最流畅方式有什么建议吗?我在想我不应该使用 :remote=>true 而是让表单插件完成工作。
  • 那个插件太棒了——刚刚试了一下,效果很好。感谢您提供信息丰富的问题​​:)

标签: ruby-on-rails ruby ajax file-upload ruby-on-rails-4


【解决方案1】:

看看remotipart gem:https://github.com/JangoSteve/remotipart -- 只需很少的工作就能让您一路走好!

【讨论】:

  • 很多未解决的问题,我特别被那些关于 rails 4 兼容性的人吓坏了
  • 我使用了带有 rails 4 的 remotipart,图像已上传,但响应 update.js.erb 没有被执行。 PLz帮助
  • 仅供参考,这也适用于带有 Turbolinks 5 的 Rails 5。
【解决方案2】:

使用@rails/ujs

查看(.html.erb):

<%= file_field_tag :file, { id: "ajax_file_upload"} %>

控制器(_controller.rb):

def update
  @record = YourModel.find(params[:id])

  respond_to do |format|
    if @record.update_attributes(params[:your_model])
      format.json { render json: { success: true } }
    else
      error_messages = @record.errors.messages.values.flatten
      format.json { render json: { success: false, errors: error_messages } }
    end
  end
end

javascript(.js)

const uploadFile = element => {
  const formData = new FormData();
  formData.append("your_model[attribute_name]", element.target.files[0]);

  Rails.ajax({
    url: "your_model/:id",
    type: "PUT",
    beforeSend(xhr, options) {
      options.data = formData;
      return true;
    },
    success: response => {
      if (response.success) {
        alert("File uploaded successfully");
      }
      else {
        alert(response.errors.join("<br>"));
      }
    },
    error: () => {
      alert("ajax send error");
    }
  });
};

const documentOnReady = () => {
  const fileField = document.getElementById("ajax_file_upload");
  if (fileField) {
    fileField.addEventListener("change", uploadFile);
  }
}

document.addEventListener("turbolinks:load", documentOnReady);

注意:使用FormData时不需要在ajax中设置RequestHeader。

FormData 使用与编码类型设置为“multipart/form-data”时表单相同的格式

【讨论】:

    【解决方案3】:

    恕我直言,在使用 AJAX 处理上传文件时,Rails 并不完美,尤其是在您需要进度条的情况下。我的建议是使用 Javascript 通过 AJAX 请求提交表单,就像您在 (2) 中建议的那样。如果你熟悉 Javascript,你不会有很多问题。

    我最近通过使用这个非常简单的 JS 库 https://github.com/hayageek/jquery-upload-file 使用了相同的方法,我在这里写了更多详细信息 http://www.alfredo.motta.name/upload-video-files-with-rails-paperclip-and-jquery-upload-file/

    对于使用表单上传带有标题和描述的电影的应用程序,JS 代码如下所示:

    $(document).ready(function() {
      var uploadObj = $("#movie_video").uploadFile({
        url: "/movies",
        multiple: false,
        fileName: "movie[video]",
        autoSubmit: false,
        formData: {
          "movie[title]": $('#movie_title').text(),
          "movie[description]": $('#movie_description').text()
        },
        onSuccess:function(files,data,xhr)
        {
          window.location.href = data.to;
        }
      });
    
      $("#fileUpload").click(function(e) {
        e.preventDefault();
        $.rails.disableFormElements($($.rails.formSubmitSelector));
        uploadObj.startUpload();
      });
    });
    

    远非完美,但为您的前端提供了灵活性。

    【讨论】:

      猜你喜欢
      • 2014-07-08
      • 2014-05-14
      • 2013-12-23
      • 1970-01-01
      • 2014-10-16
      • 2014-07-18
      • 2016-04-05
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多