My friends often asked me how to upload file using AJAX, and usually they got answer “in no way”. Correct answer, but what if I need to upload file without full page reloading? And, of course, I want to use RJS in this case. Here I’ll explain what to do to get effect very similar to AJAX file upload (btw, Gmail uses this technique).
First of all, do you know, that form element has attribute target? If you specify it your form will be submitted into frame with name entered in target attribute. Of course, this frame can be iframe, and it can be hidden! Look at the following chunk of HTML code:
<form target="upload_frame" action="/test/upload_action" id="upload_form" method="post" enctype="multipart/form-data">
<input type="file" name="uploaded_file" /><br />
<input type="submit" />
<iframe id="upload_frame" name="upload_frame" style="display: none"></iframe>
When you click the “Submit” button, form will be submitted to hidden iframe and controller’s action will be called. But resulting RJS will be returned into the hidden frame! We need to get full respond and execute it in context of whole page (parent window for our frame). There is one interesting technique exists: http://developer.apple.com/internet/webcontent/iframe.html, and it’s implementation as Ruby on Rails plugin here. Example of using:
class TestController < ActionController::Base
# Do stuff with params[:uploaded_file]
render :update do |page|
page.replace_html 'upload_form', :partial => 'upload_form'
It’s simple, right?