Sorry this page looks weird. It was automatically migrated from my old blog, which had a different layout and different CSS.

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.

Comments



Thank you very much!

Olly • 22 August 2007



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



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



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 • 6 November 2007



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 • 4 June 2009



Thank you so much for the solution!

Ales • 9 July 2009



Pretty interesting. I recently met that problem on safari 4. Fix for that looks way more weird (using yui2):

YAHOO.util.Event.addListener(“singleformUpload”, “submit”, function closeKeepAlive() {

        if (/Version\\/4\\..+\\sSafari/.test(navigator.userAgent)) {
           throw "Error";
        }
    });

demee • 14 April 2010

Andrew Stewart • 17 August 2007 • RailsNotes To Self
You can reach me by email or on Twitter.