File upload hang in Safari 4 | arfore dot com

While working on a method to allow the VSU Communications Unit to add or change the stories in the rotation on the main VSU webpage, I ran into a problem that involved a known Safari issue involving file uploads.

I don’t regularly create forms that allow for an upload of a file, however I don’t like to store binary data in the MySQL database either. Allowing the files to be uploaded makes creating pages that use them a whole lot easier, since I don’t have to “create” the image from the binary data, just pass off a file location and let the browser do the rest.

The symptoms exhibited were that when submitting the form, Safari would hang about 30-40% of the time. No error messages or timeout messages were displayed. Zip, zilch, nada!

After doing a little fiddling I determined that it was only happening in Safari on Mac OS X, as the form worked splendidly in Firefox (both Windows and Mac OS X), Internet Explorer and Safari on Windows. After a little more searching, I ran across quite a few posts on this problem going back as far as 2006.

The problem seems to center around the use of HTTP Persistent Connections in conjunction with a form using multipart data. The solution is to ensure that connection is closed after the submission.

There are multiple ways to handle this situation depending on the language being used, however the one I implemented came from a blog post at AirBlade Software.

It is simple enough.  Just create a Javascript function to implement a “ping close” by a new Ajax request when the form is submitted.  Here’s the code for the Javascript that is called with the onsubmit:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
 
/* 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 });
 
}
 
}
 

The explanation behind the workings of the function are contained in the comment preceding the function.

Thanks to Andy Steward for posting on this.

References:

%d bloggers like this: