Note To Self: Prevent Uploads Hanging In Safari

I always learn a lot reading other people’s code. (Admittedly the lesson is sometimes to run in the opposite direction as fast as possible.) This morning I was looking at Basecamp’s file upload interface which is lovely and clean.

In each file’s form’s onsubmit handler I noticed a call to closeKeepAlive(). Here’s what it looks like:

/* A pretty little hack to make uploads not hang in Safari. Just call this
 * immediately before the upload is submitted. This does an Ajax call to
 * the server, which returns an empty document with the "Connection: close"
 * header, telling Safari to close the active connection. A hack, but
 * effective. */
function closeKeepAlive() {
  if (/AppleWebKit|MSIE/.test(navigator.userAgent)) {
    new Ajax.Request("/ping/close", { asynchronous:false });
  }
}

Nice.

Andy Stewart, 17 August 2007

Posted in Notes To Self, Rails


  1. Thank you very much!

    Olly
    22 August 2007
  2. I installed this workaround and I noticed that I was still seeing the Safari/Webkit 'hang problem'. After a bit of investigation I think I've found the problem.

    I had a disable_with value set on my submit tag which itself calls this.form.submit() which appears to override any other onsubmit handler you define.

    For now I have removed the disabled_with tag but I'd be interested in a solution which would allow me to keep the disabled behaviour.

    Olly
    24 October 2007
  3. I suggest overriding the FormTagHelper's submit_tag method, or perhaps writing your own helper method based on that one, to give you the behaviour you want.

    You could have it recognise a :keep_alive option and do the right thing.

    Andy Stewart
    24 October 2007
  4. As of changeset 6134 a form using :disable_with will trigger its onsubmit handler if available.

    Rather than having your :disable_with value call this.form.submit(), wouldn't it be better to let the form take care of it as per 6134?

    Andy Stewart
    06 November 2007
  5. Thanks!

    I added these lines to my admin.js file to automatically make forms with uploads use this hack/patch:

    
    var Document = {
      initialize: function(){
        $$('form[enctype="multipart/form-data" ]').each(function(uploadForm) {
          uploadForm.observe('submit', closeKeepAlive);
        });
      }
    }
    
    Event.observe(document, 'dom:loaded', Document.initialize);
    
    Martin S
    04 June 2009

Have your say

You can use Markdown in your comments. If you want to post code, do this:

<pre><code class="ruby|javascript|css|html">your code here</code></pre>

Thanks!