Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Problems saving in iOS Safari #12

Closed
2 of 4 tasks
gawry opened this issue Jan 8, 2013 · 176 comments
Closed
2 of 4 tasks

Problems saving in iOS Safari #12

gawry opened this issue Jan 8, 2013 · 176 comments
Labels

Comments

@gawry
Copy link

gawry commented Jan 8, 2013

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 use window.URL, fallback to window.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 like image/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 a data: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
  • 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

  1. download attribute in safari is not supported
  2. It will try other means to save the blob by opening a new url
  3. If the mimetype can be rendered by safari it will be able to display it in a new tab
  4. 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 not application/octet-stream and the saveAs was not called synchronous
  5. Safari don't have anything like msSaveAs()
  6. 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)
  7. when saving it as a attachment filename will be "unknown"
@noway
Copy link

noway commented Jan 24, 2013

Your Blob.js uses native blob constructor in Google Chrome, no?
This is defined by this line:

if (typeof Blob !== "function")

@ggozad
Copy link

ggozad commented Jan 27, 2013

I can verify that Filesaver does not work with 6.0.2. Safari does have a native Blob constructor.
When Blob.js is not included, a new window opens with a blob: url which safari cannot open.
If Blob.js is included, a data: url opens. However the data seems to be the base64 representation of toString of the datea used to construct the blob. In my case where I construct from an array of bytes, I get [object Uint8Array].

Both Chrome, as well as Firefox (opening in a new window as blob) work as advertised.

@bendavis78
Copy link

Does anyone know of a workaround for this?

@marktheunissen
Copy link

marktheunissen commented Jun 17, 2013

This doesn't work on Safari. I suggest updating your REAME.md file so that people are aware of the regression.

@eligrey
Copy link
Owner

eligrey commented Jun 17, 2013

As I do not have a Mac, I really have no idea what exactly is causing the issue. It's up to you Mac users to fix this or donate a Mac/MacBook to me.

@eligrey eligrey reopened this Jun 17, 2013
@eligrey
Copy link
Owner

eligrey commented Jun 17, 2013

Apparently just mentioning an issue in a commit closes the issue. I didn't mean to do that.

@marktheunissen
Copy link

Thanks for updating that. Mountain Lion does run in VirtualBox, if you're interested.

http://www.macbreaker.com/2013/01/iatkos-ml2-mountain-lion-virtualbox.html

@eligrey
Copy link
Owner

eligrey commented Jun 17, 2013

I used to run OSX in VirtualBox and updates to VB or OSX broke compatibility every so often, so I'd rather not. The lack of hw acceleration is also pretty important.

If you are not a developer you can pay someone who is and owns a Mac to fix this bug if donating a MacBook to me is too much for you. Frankly, seeing as FileSaver.js is a tool for developers most of you are probably developers and you should have no trouble debugging the issue at hand.

@Keyamoon
Copy link
Contributor

I tried to reproduce and fix this issue but everything works fine for me in Safari 6 on OS X.

@eligrey
Copy link
Owner

eligrey commented Jun 21, 2013

@gawry @noway421 @ggozad @bendavis78 @Buttyx @marktheunissen Are you using Blob.js? Is URL, DOMURL, or webkitURL defined in Safari 6? If not, then I can guess that there is no issue and that everyone here is just neglecting to include Blob.js. The Blob API is not solely the Blob constructor, but also the URL.createObjectURL utility. If a browser does not support both of these things, then it needs Blob.js.

@marktheunissen
Copy link

@eligrey I'm using Safari 6, and doing testing on the demo page: http://eligrey.com/demos/FileSaver.js/

When clicking the 'Save' button, a new tab opens with the text in it and the url "data:text/plain..." in the address bar.

screen shot 2013-06-21 at 9 00 44 am

screen shot 2013-06-21 at 9 01 07 am

screen shot 2013-06-21 at 9 01 18 am

@eligrey
Copy link
Owner

eligrey commented Jun 21, 2013

@marktheunissen Thanks. Is URL, DOMURL, or webkitURL defined? If none of those are defined then it seems to be working properly.

@marktheunissen
Copy link

screen shot 2013-06-21 at 9 05 28 am

@eligrey
Copy link
Owner

eligrey commented Jun 21, 2013

Tell me if this fixes it for you: eligrey/Blob.js@6f36e8a

@marktheunissen
Copy link

I don't have an implementation of FileSaver anywhere to test this change, sorry. I'll let one of the others chime in, as we have moved to a different solution. Thanks for the help.

@eligrey
Copy link
Owner

eligrey commented Jun 21, 2013

An implementation of FileSaver for testing the change.

@jordanaustin
Copy link
Contributor

I use FileSaver.js on a web application and I have support on mobile Safari and Safari on OS X desktop. As long as you include Blob.js as described in the README it works. Please note that Safari has support for Blob constructor but you cannot navigate to a Blob URI, therefore it has to fallback on a Data URI and the data will open in a new window.

There is an issue in Blob.js when attempting to save large images, but that is unrelated to the bug being reported here.

I think this reported bug should be closed unless someone has a specific demo showing the issue described.

@marktheunissen
Copy link

@missing What version of Safari? This bug only exists in Safari 6 as far as we know.

I just tried the implementation as provided by @eligrey above in the 'demo' folder on master, and the bug remains.

@marktheunissen
Copy link

@missing Yes, it does open the data: URI in a new tab (as you can see in my screenshot above), but isn't the point of this library to make the browser save the file locally?

The other problem is that you can't provide a default filename in this 'fallback' mode, so the user has to re-type it.

@jordanaustin
Copy link
Contributor

@marktheunissen I have it working on Safari 6.0.5. So on this demo page it doesn't work? http://eligrey.com/demos/FileSaver.js/

@marktheunissen
Copy link

Well, it doesn't behave as expected. It does provide a fallback where you get a data: url, and that does show the correct data in the tab. The problem is that it doesn't trigger the browser to automatically download the data, and when a user chooses "Save As" from the File menu, they have to re-type the name of the file that they typed on the first page.

I'm not sure if this can be fixed by any library, it's probably a deficiency in the Safari browser. All I'm saying is that the user experience provided to Safari users is so different to other browsers, that this should be emphasized in the README so that implementers are aware of it.

@eligrey
Copy link
Owner

eligrey commented Jun 25, 2013

@marktheunissen Btw, you may be getting a cached version of the page as I have the site configured with pretty aggressive caching, so try clearing your cache before trying again.

and when a user chooses "Save As" from the File menu, they have to re-type the name of the file that they typed on the first page

Safari does not support saving filenames, only Chrome and Firefox (and possibly the new Opera) do at this time.

@jordanaustin
Copy link
Contributor

@marktheunissen I understand the frustrations, I've been fighting with Safari and downloading data for a long time as well. The sad fact is that Safari hasn't implemented any of the other fallbacks that can be used here. This library first tries to use the W3C version of FileSaver and then goes to the anchor tag download attribute and finally to data URI. Mobile Safari on iOS handles data URIs in a special way however, if you mimetype it with text/csv for example when it pops you into the new window you'll get the iOS "Open In" bar which lets you open in other applications on your device that have registered as opening csv.

In my opinion Safari hasn't implemented these other filesystem apis because they don't expose the filesystem to users on iOS. Maybe we can update the README to better reflect that.

As of right now filenames work on the follow: Chrome, Firefox 20+ & Opera NEXT (new version of the Blink rendering engine).

@marktheunissen
Copy link

Sure thing. I'm not desperate for this bug to be solved in Filesaver, because we aren't using the library. I'm just helping out with testing.

I guess the point is that most people would read the compatibility charts on the README file and expect that the user experience is the same across all browsers - that's the point of a shim like this.

To have a very different user experience for one browser could be a deal breaker for a developer, and it sucks to have to go and test the library before discovering that on Safari it isn't consistent.

@eligrey
Copy link
Owner

eligrey commented Jun 25, 2013

@missing @marktheunissen I updated the readme to make it clear which browsers support saving filenames and which don't. As it stands, IE10, Firefox, Chrome, and Opera Next support it.

@jordanaustin
Copy link
Contributor

@eligrey thanks, was just about to say IE10 too.

@badray
Copy link

badray commented Sep 4, 2013

I got issue with using FileSaver on Safari 6.0.5 on OSX. Including or not the Blob.js does not change nothing. Every time it just redirects me to:
blob:http://myhost/{blob_id}
like:
r6ec

Code sample in coffeescript:

file_parts = []
file_parts.append([1,2,3,4])
file_parts.append([5,6,7,8])
blob = new Blob(file_parts, {type: "application/octet-stream"})
downloaded_file_name = 'file_name'
saveAs(blob, downloaded_file_name)

Looking further for any patches. I also can help with testing it on OSX ;).

@jordanaustin
Copy link
Contributor

@badray what about if you try the demo found here: http://eligrey.com/demos/FileSaver.js/

@tayfunyasar
Copy link

tayfunyasar commented Oct 11, 2017

It still doesn't work on my tablet.
IOS: 11.0.2 (15A421)

var wbout = XLSX.write(wb, {
  bookType: 'xlsx',
  bookSST: false,
  type: 'binary',
});
fileSaver.saveAs(new Blob([s2ab(wbout)], {
  type: 'application/octet-stream',
}), name);

@Cabinet20
Copy link

I can agree with @tayfunyasar, it's not working on iOS for me. I have submitted a bug report to Apple regarding the lack of download attribute for all the good it's likely to do.

@eligrey eligrey changed the title Problems saving in some versions of Safari Problems saving in iOS Safari Dec 7, 2017
@dotnetCarpenter
Copy link

It's only fixed on Desktop Safari. iOS safari does still not (iOS 12.1) support the download attribute.
https://bugs.webkit.org/show_bug.cgi?id=167341

@pawepaw
Copy link

pawepaw commented Dec 18, 2018

It still doesn't work on my tablet.
IOS: 11.0.2 (15A421)

var wbout = XLSX.write(wb, {
  bookType: 'xlsx',
  bookSST: false,
  type: 'binary',
});
fileSaver.saveAs(new Blob([s2ab(wbout)], {
  type: 'application/octet-stream',
}), name);

So what's the recommended workaround for that? I'm facing same issue.

I understand that i can either leave 'application/octet-stream' and it'll not work on IOS Safari or change it to proper content-type 'application/pdf' in my case but it'll open file in new tab with strange url 'blob:something'? Is there any other chance to force saving file in safari ios?

@generalov
Copy link

@pawepaw I suppose that the opening in new tab is expected behavior for Safari <12 on iOS because the browsers do not have an access to file system. This gives the user a chance to save a file with an additional click to the cloud storage.

@dotnetCarpenter
Copy link

dotnetCarpenter commented Jan 9, 2019

I can save a file on iOS but not give it a name. @pawepaw See here: https://dotnetcarpenter.github.io/FileReader_Chrome/

@crisz
Copy link

crisz commented Apr 19, 2019

This is still not working on iOS, with the exact same symptoms as described above. In my opinion this issue should not be closed

@classicPintus
Copy link

Confirm for me also. Unfortunately the problem is still there

@Jason-LI-M
Copy link

I can save a file on iOS but not give it a name. @pawepaw See here: https://dotnetcarpenter.github.io/FileReader_Chrome/

Not working

@Cabinet20
Copy link

This is resolved in the new safari in iOS 13 with the introduction of three download manager.

@Stofkat
Copy link

Stofkat commented Jul 17, 2019

can this be reopened? this is still an existing issue

@IhorBilobran
Copy link

IhorBilobran commented Aug 28, 2019

I had the same issue with images download. iPhone, Safari. This helped:
const blob = new Blob([file], { type: 'image/jpeg' });
const url = window.URL.createObjectURL(blob);
saveAs(url, fileName);

@DevJhns
Copy link

DevJhns commented Jan 21, 2020

I had the same issue with images download. iPhone, Safari. This helped:
const blob = new Blob([file], { type: 'image/jpeg' });
const url = window.URL.createObjectURL(blob);
saveAs(url, fileName);

this code allowed you to DOWNLOAD file in your file system or OPEN it in safari tab?

@HansLanger
Copy link

HansLanger commented Apr 7, 2020

2020 and still the same problem? UNKNOW as name, and can't download octet-stream?? wow.
I'm lucky because i can say to my users "Safari is not a modern browser, just use chrome,firefox or edge"

@snipe
Copy link

snipe commented Apr 7, 2020

@HansLanger Maintaining open source projects takes a lot of time, and sometimes people's priorities change, and life gets in the way. People create software and let you use it for free, so maybe don't be an ass in the face of free labor. Having a crappy attitude doesn't get problems solved any faster.

@HansLanger
Copy link

@snipe: If you understand the problem you would understand that I was NOT complaining about FileSaver.js. I was complaining about Safari (which is not free). Sorry for the confusion.

@snipe
Copy link

snipe commented Apr 7, 2020

@HansLanger thanks for the clarification. (Safari is free, if you don't mind dropping $1k on an iPhone ;-) )

Did you try the solution @DevJhns mentioned?

@HansLanger
Copy link

@HansLanger thanks for the clarification. (Safari is free, if you don't mind dropping $1k on an iPhone ;-) )

Did you try the solution @DevJhns mentioned?

Yes, I tried everything on an Iphone. It just does not work. The Initial @gawry post describes everything perfectly, its a great information, but Apple has not solve the problem, and that is why my first comment.

@JamesDougherty
Copy link

Looks like the "download" attribute was added in iOS 13 as of April 2020.

Support for the "download" attribute was added in iOS 13.0.

If you have a specific use case with the "download" attribute that doesn't work in iOS 13.0 or later, you need to file a new bug here on bugs.webkit.org with steps to reproduce and (if possible) a > reduced test case that will reproduce the issue.

https://bugs.webkit.org/show_bug.cgi?id=167341

@seanlee10
Copy link

I had the same issue with images download. iPhone, Safari. This helped:
const blob = new Blob([file], { type: 'image/jpeg' });
const url = window.URL.createObjectURL(blob);
saveAs(url, fileName);

this code allowed you to DOWNLOAD file in your file system or OPEN it in safari tab?

I tried it and the file was opened in current tab. it didn't download.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests