使用Remotipart的Rails AJAX上传表单

时间:2022-08-28 09:31:56

I've been bashing my head trying to get an AJAX upload form working. I'm using Rails 3.2. I put gem "remotipart", "~> 1.0" in my Gemfile, ran bundle install and it installed successfully.

我一直在试图让AJAX上传表单正常工作。我正在使用Rails 3.2。我在我的Gemfile中放了gem“remotipart”,“〜> 1.0”,运行bundle install并成功安装。

I previously had this non-ajax upload form, which I added :remote => true to as per the literature on the github page :

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

<%= 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>

and this in my data_imports_controller create action:

这在我的data_imports_controller创建动作中:

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

I added a javascript include on my page for jquery.remotipart.js because it felt essential, albeit there being no explicit instruction to do so..

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

I tried it and it failed giving a server error:

我尝试了它,它没有给出服务器错误:

Completed 500 Internal Server Error in 4ms

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

It's clear I'm doing something fundamentally wrong, but I need a hand.

很明显我做了一些根本错误的事情,但我需要一只手。

5 个解决方案

#1


3  

After a ton of debugging and reading through lots of code, I finally have the latest gem (1.0.2) working with Rails 3.2.8. I was nailed by three gotchas:

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

  1. I was disabling my file input field prior to form submission and this causes remotipart to ignore it for inclusion in the iframe submission. You must make sure your file inputs are enabled. This is probably what you are seeing, and why specifying a different selector for the 'files' attribute works for you.
  2. 我在表单提交之前禁用了我的文件输入字段,这导致remotipart忽略它以包含在iframe提交中。您必须确保已启用文件输入。这可能就是您所看到的,以及为什么为'files'属性指定不同的选择器适合您。
  3. In the course of my debugging, I was overriding jquery.iframe-transport with the latest upstream source and it doesn't have support for the X-Http-Accepts hidden variable in the iframe. You must use the version bundled with the remotipart gem.
  4. 在我的调试过程中,我用最新的上游源覆盖了jquery.iframe-transport,并且它不支持iframe中的X-Http-Accepts隐藏变量。您必须使用与remotipart gem捆绑在一起的版本。
  5. Don't forget to wire up a callback for ajax:complete on the form if you are using a datatype other than 'script'. This is the default if you don't specify dataType in the global ajax options, or use the data-type attribute on the form.
  6. 如果您使用的是'script'以外的数据类型,请不要忘记为ajax连接回调:在表单上完成。如果未在全局ajax选项中指定dataType,或者在表单上使用data-type属性,则这是缺省值。

#2


1  

Managed to achieve something along the lines of what I wanted by bodging in a way I don't really understand but hey, it kinda works. I had to add some jQuery along the lines of:

通过一种我并不理解的方式来实现某些想法,但是嘿,它有点有效。我不得不添加一些jQuery:

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

Which I believe takes over the form submission, initiates an ajax post with this iframe-transport lark and then evaluates what is returned (because in my case I'm returning javascript). I also had to remove :remote => true from the form else it was posting twice or something.

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

Thought I'd post that here so that it can either help someone out or lead someone to doing it better.

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

#3


1  

Lucky you. I had the exact same problem some time ago. :) Add this to your application.js:

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

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

You can get the 'iframe-transport' file from here: http://cmlenz.github.com/jquery-iframe-transport/.

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

And as I said as a comment to another answer: I believe :multipart isn't needed, because you're using Rails 3.2. Not 100% sure, because I'm still using Rails 3.1 at work. ;)

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

Hope it helps!

希望能帮助到你!

Edit

I created an example app showing how to add remotipart to enable AJAX file uploading. It works great for me.

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

https://github.com/RobinBrouwer/remotipart_example

https://github.com/RobinBrouwer/remotipart_example

See the commits inside that repository for the steps that were taken.

请参阅该存储库中的提交以了解所执行的步骤。

#4


1  

In my case I had the old version of jquery.iframe-transport.js

在我的情况下,我有旧版本的jquery.iframe-transport.js

#5


0  

The problem is how you are actually declaring your :multipart=> true

问题是你如何实际声明你的:multipart => true

Please use the code below and your form will then accept the file parameter.

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

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

#1


3  

After a ton of debugging and reading through lots of code, I finally have the latest gem (1.0.2) working with Rails 3.2.8. I was nailed by three gotchas:

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

  1. I was disabling my file input field prior to form submission and this causes remotipart to ignore it for inclusion in the iframe submission. You must make sure your file inputs are enabled. This is probably what you are seeing, and why specifying a different selector for the 'files' attribute works for you.
  2. 我在表单提交之前禁用了我的文件输入字段,这导致remotipart忽略它以包含在iframe提交中。您必须确保已启用文件输入。这可能就是您所看到的,以及为什么为'files'属性指定不同的选择器适合您。
  3. In the course of my debugging, I was overriding jquery.iframe-transport with the latest upstream source and it doesn't have support for the X-Http-Accepts hidden variable in the iframe. You must use the version bundled with the remotipart gem.
  4. 在我的调试过程中,我用最新的上游源覆盖了jquery.iframe-transport,并且它不支持iframe中的X-Http-Accepts隐藏变量。您必须使用与remotipart gem捆绑在一起的版本。
  5. Don't forget to wire up a callback for ajax:complete on the form if you are using a datatype other than 'script'. This is the default if you don't specify dataType in the global ajax options, or use the data-type attribute on the form.
  6. 如果您使用的是'script'以外的数据类型,请不要忘记为ajax连接回调:在表单上完成。如果未在全局ajax选项中指定dataType,或者在表单上使用data-type属性,则这是缺省值。

#2


1  

Managed to achieve something along the lines of what I wanted by bodging in a way I don't really understand but hey, it kinda works. I had to add some jQuery along the lines of:

通过一种我并不理解的方式来实现某些想法,但是嘿,它有点有效。我不得不添加一些jQuery:

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

Which I believe takes over the form submission, initiates an ajax post with this iframe-transport lark and then evaluates what is returned (because in my case I'm returning javascript). I also had to remove :remote => true from the form else it was posting twice or something.

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

Thought I'd post that here so that it can either help someone out or lead someone to doing it better.

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

#3


1  

Lucky you. I had the exact same problem some time ago. :) Add this to your application.js:

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

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

You can get the 'iframe-transport' file from here: http://cmlenz.github.com/jquery-iframe-transport/.

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

And as I said as a comment to another answer: I believe :multipart isn't needed, because you're using Rails 3.2. Not 100% sure, because I'm still using Rails 3.1 at work. ;)

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

Hope it helps!

希望能帮助到你!

Edit

I created an example app showing how to add remotipart to enable AJAX file uploading. It works great for me.

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

https://github.com/RobinBrouwer/remotipart_example

https://github.com/RobinBrouwer/remotipart_example

See the commits inside that repository for the steps that were taken.

请参阅该存储库中的提交以了解所执行的步骤。

#4


1  

In my case I had the old version of jquery.iframe-transport.js

在我的情况下,我有旧版本的jquery.iframe-transport.js

#5


0  

The problem is how you are actually declaring your :multipart=> true

问题是你如何实际声明你的:multipart => true

Please use the code below and your form will then accept the file parameter.

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

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