问题
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.
I previously had this non-ajax upload form, which I added :remote => true to as per the literature on the github page :
<%= 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:
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..
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.
回答1:
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:
- 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.
- 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.
- 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.
回答2:
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:
$("#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.
Thought I'd post that here so that it can either help someone out or lead someone to doing it better.
回答3:
Lucky you. I had the exact same problem some time ago. :) Add this to your 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/.
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. ;)
Hope it helps!
Edit
I created an example app showing how to add remotipart to enable AJAX file uploading. It works great for me.
https://github.com/RobinBrouwer/remotipart_example
See the commits inside that repository for the steps that were taken.
回答4:
In my case I had the old version of jquery.iframe-transport.js
回答5:
The problem is how you are actually declaring your :multipart=> true
Please use the code below and your form will then accept the file parameter.
form_for "/administration/data_imports",:remote => true,:html => {:multipart => true}
来源:https://stackoverflow.com/questions/11954122/rails-ajax-upload-form-with-remotipart