Description
Edit by @eligrey: Please tell Apple how this bug is affecting you in https://bugs.webkit.org/show_bug.cgi?id=102914 if you want this fixed.
Edit by @jimmywarting
The safari bug #102914 has been marked as fixed now
according to the commit position, download attribute is fixed in WebKit v602.1.27.
The latest beta build (Safari Technology Preview) is based on WebKit v602.1.25, and of course doesn't contain this patch, so there's no simple way to test.
In the meantime, if you want to support Safari 7, you'll probably want to use Downloadify (uses Flash, not HTML5).
Issues we have had with Safari
- Blob is not supported
This has been solved with Blob.js using BlobBuilder as fallback and then base64 data uri if that are not supported either - URL.createObjectUrl
Has been covered by both FileSaver.js and blob.js
Blob.js overrule createObjectUrl with it's own base64 url constructor only if it's a "fake blob" (i.e not a File or Blob representation) it will usewindow.URL
, fallback towindow.webkitURL
or use it's own base64 function to create those "fake blobs" data-uri - The "can't open blob url" issue (partly supported) - screenshot
The page you opened redirected you to a page that isn't supported by safari
Safari can't open the page becuse Safari can't be redirected to address that begin with "blob:".
- This is mostly cased by unsupported mime type, Safari do support opening blob url, but only if it's a mimetype that safari can understand like simple
plain/text
or a common image likeimage/png
.- This will result in a new tab from which the user can just hit ⌘+S to save it
- ATM FileSaver.js looks at the mimetype to see if it is
application/octet-stream
(wish is commonly used to force saving files from the server)
If it's then it read the blob as base64 using FileReader to open adata:attachment/file" + base64
url in order to save it.- It's not possible to create a blob with
attachment/file
type directly and open it, then you will get errors like this:Failed to load resource: Frame load interrupted
it has to be base64 for some reason... - the resulting filename will be "unknown" when doing this
- It's not possible to create a blob with
- The blank page error partial supported - (formuly known as "can't open blob url", see above)
This can easily be reproduced by doing:
window.onclick = function(){
var blob = new Blob(["Hi"], {type: 'application/octet-stream'});
var url = URL.createObjectURL(url);
window.open(url);
}
If you replace window.open
with location.href =
you will get the Failed to load resource: Frame load interrupted
and be unable to save the file that is not the case for all mimetype, mimetypes that Safari can display can be opened this way
A little side note here is that window.open only works on trusted events meaning:
- It will only be able to open the url when user interacts with the website like a
onclick
event (more about isTrusted event here - almost pointless becuse browser support)
I have also found out that the trusted event persist for 1000 ms, so you could do:
window.onclick = function(){
setTimeout(function(){
var blob = new Blob(["Hi"], {type: 'application/octet-stream'});
var url = URL.createObjectURL(url);
window.open(url);
}, 950); // Any longer then 1sec will make the window.open blocked again
}
So the conclusion here about safari is
- download attribute in safari is not supported
- It will try other means to save the blob by opening a new url
- If the mimetype can be rendered by safari it will be able to display it in a new tab
- If the mimetype is application/octet-stream:
4.1 Create a base64 link with FileReader api
4.2 try to open a new tab using window.open + base64 url
4.3 if it was more then 1 sec before the user interaction happened it will use the current page instead
but that is likely going to fail because (see first example using location.href)Failed to load resource: Frame load interrupted
This may still work if the mimetype is notapplication/octet-stream
and the saveAs was not called synchronous - Safari don't have anything like
msSaveAs()
- safest way to force the file to be saved is to have a
data:attachment/file" + base64
ready and open that link using window.open() when the user interacts with the website (or at least to it under 1 second) - when saving it as a attachment filename will be "unknown"