使用 Remotipart 的 Rails AJAX 上传表单

Posted

技术标签:

【中文标题】使用 Remotipart 的 Rails AJAX 上传表单【英文标题】:Rails AJAX upload form with Remotipart 【发布时间】:2012-08-10 20:27:10 【问题描述】:

我一直在努力让 AJAX 上传表单正常工作。我正在使用 Rails 3.2。我将gem "remotipart", "~> 1.0" 放入我的Gemfile 中,运行bundle install 并成功安装。

我之前有这个非 ajax 上传表单,我根据 github page 上的文献添加了 :remote => true

<%= form_tag "/administration/data_imports", :multipart => true, :remote => true %>  
    <label for="file">Input File</label> <%= file_field_tag "file" %>
    <button type="submit">Import Data</button>
</form>

这在我的data_imports_controller create 行动中:

def create
  file = params[:file]
  filename = file.original_filename
end

我在我的页面上为 jquery.remotipart.js 添加了一个 javascript 包含,因为它感觉很重要,尽管没有明确的说明这样做..

我试过了,但没有给出服务器错误:

Completed 500 Internal Server Error in 4ms

NoMethodError (undefined method `original_filename' for nil:NilClass):
app/controllers/data_imports_controller.rb:16:in `create'

很明显我做错了什么,但我需要帮助。

【问题讨论】:

您是否可以通过添加 :remote =&gt; true 选项进行更改后粘贴您的新视图文件 请尝试使用下面的答案。问题在于您如何声明您的多部分选项 如果有人想推荐我打勾的答案,请继续。我很久以前就放弃了这个想法,并且从未真正得到令人满意的解决方案,所以我不确定哪个是最好的答案,干杯! 【参考方案1】:

就我而言,我使用的是旧版本的 jquery.iframe-transport.js

【讨论】:

【参考方案2】:

经过大量调试和阅读大量代码后,我终于有了与 Rails 3.2.8 配合使用的最新 gem (1.0.2)。我被三个陷阱钉住了:

    我在提交表单之前禁用了我的文件输入字段,这导致 remotipart 忽略它以包含在 iframe 提交中。您必须确保您的文件输入已启用。这可能就是您所看到的,以及为什么为“文件”属性指定不同的选择器对您有用。 在调试过程中,我使用最新的上游源代码覆盖了 jquery.iframe-transport,它不支持 iframe 中的 X-Http-Accepts 隐藏变量。您必须使用与 remotipart gem 捆绑的版本。 如果您使用的是“脚本”以外的数据类型,请不要忘记在表单上连接 ajax:complete 回调。如果您未在全局 ajax 选项中指定 dataType 或在表单上使用 data-type 属性,则这是默认设置。

【讨论】:

【参考方案3】:

你很幸运。前段时间我遇到了完全相同的问题。 :) 将此添加到您的 application.js:

//= require jquery.remotipart
//= require jquery.iframe-transport

您可以从此处获取“iframe-transport”文件:http://cmlenz.github.com/jquery-iframe-transport/。

正如我对另一个答案的评论所说:我相信不需要:multipart,因为您使用的是Rails 3.2。不是 100% 肯定,因为我仍在使用 Rails 3.1。 ;)

希望对你有帮助!

编辑

我创建了一个示例应用程序,展示了如何添加 remotipart 以启用 AJAX 文件上传。它对我很有用。

https://github.com/RobinBrouwer/remotipart_example

查看该存储库中的提交以了解所采取的步骤。

【讨论】:

明天早上我会好好谈谈,因为我刚下班。我从来没有见过那些 require 语句,我只是把它们放在 application.js 的顶部吗? 您在使用资产管道对吗?如果不是,您应该只使用 javascript_include_tag 添加这两个文件。确保它是在包含 jquery 之后添加的。 那太糟糕了。明天,我将尝试重新创建您的问题,看看是否可以使用这两行代码来解决问题。我会把它发布到 Github。 :) 我在 Github 上创建了一个存储库。看看这个。 :) 这应该作为remotipart的票提交。【参考方案4】:

通过以一种我不太了解的方式犹豫不决,成功地实现了我想要的目标,但是嘿,它有点工作。我不得不按照以下方式添加一些 jQuery:

$("#myform").submit(function(e) 
    e.preventDefault();
    $.ajax(this.action, 
        files: $(":file", this),
        iframe: true
    ).complete( function(data) 
        eval(data.responseText);
    );
);

我相信它会接管表单提交,使用这个 iframe-transport lark 启动一个 ajax 帖子,然后评估返回的内容(因为在我的情况下我正在返回 javascript)。我还必须从表单中删除:remote =&gt; true,否则它会发布两次或其他内容。

我想我会在这里发布它,以便它可以帮助某人或引导某人做得更好。

【讨论】:

【参考方案5】:

问题是你实际上是如何声明你的:multipart=&gt; true

请使用下面的代码,然后您的表单将接受文件参数。

 form_for "/administration/data_imports",:remote => true,:html => :multipart => true

【讨论】:

他使用的是form_tag,所以他不需要添加:html。而且他使用的是 Rails 3.2,因此无论如何都不需要定义 :multipart。

以上是关于使用 Remotipart 的 Rails AJAX 上传表单的主要内容,如果未能解决你的问题,请参考以下文章

Ruby on Rails AJAX文件上传

Cucumber (rails 2) 没有加载 jQuery

Rails 通过 ajax 闪烁通知

Rails AJAX 远程:true 与动态 id

使用ajax每X秒更新一次html页面

是否有理由不将 JSONP 用于 AJA~X 请求?