In-place file upload with Ruby on Rails

Oct 28
2006 15:10 (AJAX, Development, Ruby on Rails) · Русский (48,534 views)

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">
  <input type="file" name="uploaded_file" /><br />
  <input type="submit" />
</form>
<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
  def upload_action
    # Do stuff with params[:uploaded_file]

    responds_to_parent do
      render :update do |page|
        page.replace_html 'upload_form', :partial => 'upload_form'
      end
    end
  end
end

It’s simple, right?

28 Responses to 'In-place file upload with Ruby on Rails'

Subscribe to comments with RSS or TrackBack to 'In-place file upload with Ruby on Rails'.

1
said on 2006-11-05 at 4.21 am

[...] In this short story author describes how to implement file upload without full page reloading (technique used in gmail) with Ruby on Rails.read more | digg story Share and Enjoy:These icons link to social bookmarking sites where readers can share and discover new web pages. [...]

2
Gomes
said on 2006-11-06 at 12.04 pm

Классная статья, спору нет. Созрел только небольшой вопросик как отследить загрузился ли файл на сервер, ведь существует куча преград при загрузке (размер файла превышает разрешенный и т.п.). Отдавать с сервера страницу с JavaScript, который бы дернул функцию на странице как то не красиво (да и не всегда сработает), а как узнать кроссбраузерно что пришло в теле страницы с сервера для меня загадка, если не сложно прошу расширения статьи.

3
said on 2006-11-20 at 5.04 pm

Попробуем применить на практике. Еще было бы интересно состыковать эту штуку с плагином upload_progress

4
said on 2006-11-20 at 5.10 pm

Ага, были такие мысли, займусь на досуге.

5
said on 2006-11-20 at 9.30 pm

[...] There is no way to upload files using AJAX. How Gmail does it then? Well, the answer is using <iframe>. Here is a post that describe this technique in detail. Infact we at Vinayak Solutions are using this technique from months, obviously inspired by Gmail. ;-) [...]

6
Anton Kirsanov
said on 2006-11-23 at 10.35 am

Добавлю только, что для проверки статуса достаточно запустить интервалом в секунду калбэк функцию (я о javascript говорю), которая будет смотреть readyState у окна в скрытом фрейме.

7
said on 2006-11-23 at 1.44 pm

По поводу прогресса загрузки файла, посмотрите статью Юрия Рашковского RubyOnRails: AJAX File Upload Hint.

8
said on 2006-11-23 at 6.44 pm

Спасибо, погляжу

9
Maximark
said on 2006-11-23 at 6.58 pm

По поводу загрузки файлов без обновления, напоминаю прекрасную библиотеку dklab.ru
http://dklab.ru/lib/JsHttpRequest/

Версия 4.0

я уже писал как то про неё, но эффекта было ноль. И вот… получите и спокойно пользуйтесь. На сегодня я думаю это самое лучшее реализация технологии AJAX. И тем паче загрузки файлов без перезагрузки страницы !!!
Это не реклама… я сам давно пользуюсь и не я её писал.

10
said on 2006-12-01 at 9.36 am

[...] There is no way to upload files using AJAX. How Gmail does it then? Well, the answer is using <iframe>. Here is a post that describe this technique in detail. Infact we are using this technique from months, obviously inspired by Gmail. [...]

11
said on 2007-01-04 at 2.46 am

great article! its a tricky problem but your solution works like a charm ;-)

12
Rails Developer
said on 2007-01-29 at 9.00 pm

Thanks for the help but from the Apple site, %{style=”display: none”} doesn’t work on the iframe but if you set it to %{style=”height:0;width:0;border:0;”} then it will work.

13
said on 2007-02-12 at 11.58 pm

Hey, nice article.. I actually wrote a plugin that does this. I’m using it in a couple places, but had to write it so quickly that I wasn’t able to adequately test it on all platforms. You can check it out here: http://rubyforge.org/projects/remote-upload/

Please tell me what you think

14
said on 2007-02-14 at 1.44 am

[...] Dmytro Shteflyuk’s Home » In-place file upload with Ruby on Rails (tags: ruby rubyonrails rails tutorial reference howto) [...]

15
John
said on 2007-02-16 at 7.20 pm

I’m using your code almost exactly and most of it seems to be working, but when i try to do something with the uploaded_file all it has is the filename, not the actual file data. Any ideas?

16
said on 2007-02-22 at 1.09 am

Rails Developer, great thanks for the tip!

17
said on 2007-02-22 at 1.20 am

Jeff, great news! Will check your plugin in short time. Thanks!

18
said on 2007-03-13 at 7.17 pm

Great article! Thanks! I’ve combined your solution with attachment_fu plugin and result is awesome! Thanks!

19
said on 2007-04-23 at 11.37 am

Спасибо а идею реализации. Думаю что этой техникой можно пользотаться и в других случаях.

20
jeffguroo
said on 2007-12-11 at 12.22 am

Seems as though the problem with the lack of data being transfered is a problem with Firefox. When I use ff the files are always empty, however when I use Exploder, the data is carried over.

21
jeffguroo
said on 2007-12-11 at 12.24 am

this solution only seems to work on txt files. Formatting for PDFs and Word Docs were hosed.

22
jeffguroo
said on 2007-12-12 at 12.26 am

Alright, that was because I was trying to do it with remote_form instead of a form_for. Only the text was making it through. BTW what was the name of the plugin that was used for returning js to the iframe? That link is dead.

23
jeffguroo
said on 2007-12-12 at 2.46 am

The above mentioned plugin is: respondes_to_parent

24
said on 2007-12-12 at 6.35 am

jeffguroo, you right
It’s impossible to upload file using AJAX’s XMLHttpRequest. So I have written this post to show how to do it using iframe.

Thanks for comment about broken link, I have fixed it.

25
jeffguroo
said on 2007-12-12 at 7.34 am

after beeting my head against this all day, I have found that doing a simple

render :partial => "successful_attachment"

also works quite well in Rails v1.2.3 and the acts_as_attachment plugin. Thanks for the file upload/AJAX workaround… a lifesaver.

26
said on 2008-01-07 at 4.08 am

All you really need is the first part. The form’s target=”IFrameName” is all that really matters.

As far as the IFrame. You can give it a width and height, and then any text that you generate in the php upload file will show there.

Really simple.

27
said on 2008-02-05 at 4.45 pm

Hi I have tried this in my app. In my app, I have a partial to display my form to upload files and in another partial i am listing the files uploaded. right now I have to redirect the page after uploading the files. But how display my file list partial initially and update it with adding the newly added file info every time i upload a new file…
any help appreciated

regards,
venkat

28
said on 2008-05-08 at 1.35 pm

[...] In-place file upload with Ruby on Rails - The GMail technique for asynchronous uploads. [...]

Post a comment

You can use simple HTML-formatting tags (like <a>, <ul> and others). To format your code sample use <code lang="php">$a = "hello";</code> (allowed languages are ruby, php, yaml, html, csharp, javascript). Also you could use <code>$a = "hello";</code> and its syntax would not be highlighted. If you are not using <code> tag, replace < sign with &lt;.

Submit Comment

 
Copyright © 2005 - 2008, Dmytro Shteflyuk