MrOliv
July 13, 2021, 5:56am
#1
https://developer.playcanvas.com/en/tutorials/capturing-a-screenshot/
It looks like the good old Screenshot example project doesn’t work on iOS Chrome (or Firefox for that matter). Chrome does show a popup to download the file, but it doesn’t know what it’s downloading, it’s just a “document” without file format, and it doesn’t open as an image. iOS Safari works just fine.
Has anyone been able to find a workaround?
Hi @MrOliv ,
Confirmed, tested on an iPhone X / iOS 14/ Chrome and I get the document named file that can’t be opened.
On Safari though it worked as expected, a screenshot.png was downloaded.
Not sure why that happens on Chrome, I’ll investigate and let you know.
1 Like
Hmm, this is a hard one, many people seem to have the same issue. I wasn’t able to find a solution online.
opened 07:36PM - 02 Dec 20 UTC
Hello, I am having trouble downloading an image on Chrome iOS 87.0.4280.77. I am… using an iPhone 12 running iOS 14.3-beta. I am taking a screenshot with MediaRecorder and then creating a blob with `const currentBlob = new Blob([buffer], {type: 'image/jpeg'})`. My goal is to be able to trigger a download of the image, with the name and file extension set.
### Issue: Testing with FileSaver.js with code from `v2.0.4` or `master`
When I call `saveAs(currentBlob, "name.jpg")`, the file pops up in a new tab. I can long press on it and get the ability to save to photos (and other things), but I want a direct download.
For both versions of FileSaver.js I have tried changing the type of the blob (b/c I have read that may force Chrome to automatically download the file), but that results in no tab being opened and no download pop-up:
```
const currentBlob = new Blob([buffer], {type: 'image/jpeg'})
const rawBlob = new Blob([currentBlob])
const octetBlob = new Blob([currentBlob], {type: 'application/octet-stream'})
saveAs(blob / rawBlob / octetBlob, "name.jpg")
```
For contrast, Safari iOS shows the system dialog for a download in all three of these cases, with both versions of FileSaver.js.
### Solution Attempt 1: Using `a` to download the image
The basic way to download a file is below. This results in the image being opened in a new window with no download prompt:
```
const currentBlob = new Blob([buffer], {type: 'image/jpeg'})
const a = document.createElement('a')
a.download = currentName
a.href = URL.createObjectURL(currentBlob)
a.rel = 'noopener'
document.body.appendChild(a)
click(a)
document.body.removeChild(a)
```
If I instead encode the Blob into a Base64 encoded string with [`readAsDataURL`](https://developer.mozilla.org/en-US/docs/Web/API/FileReader/readAsDataURL), I can get the file to download, but it is named 'document' and has no file extension (though if I rename the file to "name.jpg" then I can see it is in fact an image):
```
const currentBlob = new Blob([buffer], {type: 'image/jpeg'})
const reader = new FileReader()
reader.onloadend = () => {
const a = document.createElement('a')
a.download = currentName
a.href = reader.result // I.e. data:image/jpeg;base64,/9j/4AA...
a.rel = 'noopener'
document.body.appendChild(a)
click(a)
document.body.removeChild(a)
}
reader.readAsDataURL(currentBlob)
```
<img src="https://user-images.githubusercontent.com/1396242/100920754-6c30bb00-3490-11eb-9cb6-f41ddf9cd320.PNG" alt="alt text" width=200>
<img src="https://user-images.githubusercontent.com/1396242/100920760-6e931500-3490-11eb-81bf-1f70f56dffd0.PNG" alt="alt text" width=200>
I have also tried changing the Base64 encoded string in several ways to try to rename the file, but to no effect.
```
reader.onloadend = () => {
...
const url = reader.result
const urlWithHeaders = url.replace(';', `;name=${currentFilename};headers=Content-Disposition%3A%20attachment%3B%20filename=%22${currentFilename}%22;`)
const urlFile = url.replace(/^data:[^;]*;/, 'data:attachment/file;')
const urlOctet = url.replace('image/jpeg', 'binary/octet-stream')
a.href = url / urlWithHeaders / urlFile / urlOctet
...
}
```
### Solution Attempt 2: Using a new window
I have also tried by opening a new window, but it just opens the image in a new window and does not prompt a download:
```
const currentBlob = new Blob([buffer], {type: 'image/jpeg'})
const newWindow = window.open(URL.createObjectURL(currentBlob), '_blank')
```
### Questions
* Is Chrome iOS downloading supported with FileSaver.js?
* Is this a known limitation of Chrome iOS?
There are several issues that seem potentially related, but all of them are quite old and haven't focused on images specifically: https://github.com/eligrey/FileSaver.js/issues/506, https://github.com/eligrey/FileSaver.js/issues/576, https://github.com/eligrey/FileSaver.js/issues/343
I have also tried with an mp4 but, just like these questions describe, it is not working:
- https://stackoverflow.com/questions/63848034/anchor-download-attribute-created-with-javascript-not-working-on-ios-chrome
- https://stackoverflow.com/questions/64969672/unable-to-download-files-with-the-correct-name-in-chrome-on-ios
The closest I’ve come is to use a blob instead of a base64. That opens the screenshot on a new tab, not ideal but I think it’s a start.
fetch(this.canvas.toDataURL("image/png"))
.then(res => res.blob())
.then(blob => window.open(URL.createObjectURL(blob)) );
If you aren’t able to solve this, I think the real workaround is to use a server to send the image data to and serve back a download url.