Sep 19, 2014

File uploads appear to be broken in Safari on iOS 8

Uploadcare users have noticed that after upgrading to iOS 8.0 they cannot upload files from Safari.

Sad but true. New iOS version has a bug that renders sending files by browsers impossible. When you choose a file in a form on HTML page and try to submit it, no file is sent in request. Browser indicates that it’s waiting for response, but in fact response never comes.

Furthermore, bug does not affect only HTML forms. If you try to send a file via Javascript constructing a FormData object (part of XMLHttpRequest level 2), you get same results. Even if you do this in native app that is just a wrapper over HTML browser (e.g. Apache Cordova), nothing good happens.

So why there’s no response? If no file is submitted server would respond with an error that file is required or file is empty. But there’s no response at all (even HTTP 400 Bad Request) and connection is closed by timeout. The culprit is request sent by Safari.

POST /form/ HTTP/1.1
Host: 192.168.5.59:8000
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryGVP84V9BXQSqpZw2
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Content-Length: 134573
Accept-Language: ru
Accept-Encoding: gzip, deflate
Connection: keep-alive
User-Agent: Mozilla/5.0 (iPhone; CPU iPhone OS 8_0 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) Version/8.0 Mobile/12A365 Safari/600.1.4

------WebKitFormBoundaryGVP84V9BXQSqpZw2
Content-Disposition: form-data; name="file"; filename="image.jpg"
Content-Type: image/jpeg


------WebKitFormBoundaryGVP84V9BXQSqpZw2--

We can see that request length should be 134573 bytes (Content-Length header), but as file is absent from request and real length is only 176 bytes. Server is waiting for the rest 134397 bytes, browser is waiting for response as it’s sure that complete request is sent. But nothing happens and connection is closed by timeout.

The bug manifests itself in Safari 8.0 (build 600.1.4) on iOS 8.0 (build 12A365). Fun fact: everything is ok on iOS Simulator that is bundled with XCode. We could reproduce the bug on hardware we could get our hands on (iPhone 4S, iPhone 5, iPad 3). We sure hope that this will be fixed in future minor update.

You may want to reproduce the bug yourself

All you need is a form with a file field and a server that can accept uploads. There is online example.

<form action="http://upload.uploadcare.com/base/?jsonerrors=1"
method="post" enctype="multipart/form-data"> <input type="hidden" name="UPLOADCARE_PUB_KEY"
value="demopublickey"> <input type="file" name="file"> <input type="submit"> </form>

To check that this is indeed iOS8 bug you have to inspect HTTP request body. Unfortunately Safari Web Inspector cannot be of help here as it doesn’t show file bodies in request. You can run a listening TCP-server on same subnet using netcat utility:

netcat -l 8000

You have to change form’s “action” attribute so that IP address and port point to your running server (e.g. http://192.168.1.101:8000/). You can fork jsbin and save your own. Then you can open a form in Safari and send any file. If everything is correct you will see raw HTTP request in netcat’s output.

If file body is included in payload you’ll see a bunch of “garbage” on your screen.

Blog comments powered by Disqus