<!DOCTYPE html> <html> <head> <meta charset="utf-8"> </head> <body> <button id="download">Download</button> <iframe id="iframe" sandbox="allow-scripts allow-downloads allow-downloads-without-user-activation"></iframe> <script type="text/javascript"> const iframeHtml = ` <!DOCTYPE html> <html> <head> <meta charset="utf-8"> </head> <body> <a id="link" href="#">Link to progamatically click</a> <script type="text/javascript"> var link = document.getElementById("link"); function downloadBlob(blob, filename) { var url = URL.createObjectURL(blob); link.href = url; link.download = filename; link.innerText = url; link.click(); URL.revokeObjectURL(url); } function toBase64(buffer) { let binaryStr = ""; const bytes = new Uint8Array(buffer); for (let i = 0; i < bytes.byteLength; i++) { binaryStr += String.fromCharCode(bytes[i]); } return window.btoa(binaryStr); } function downloadBuffer(buffer, mimeType, filename) { var url = "data:" + mimeType + ";base64," + toBase64(buffer); link.href = url; link.download = filename; link.innerText = url; link.click(); } window.addEventListener("message", async function(event) { // if (event.origin === window.location.origin) { if (event.data.type === "downloadBuffer") { await downloadBuffer(event.data.buffer, event.data.mimeType, event.data.filename); } else if (event.data.type === "downloadBlob") { await downloadBlob(event.data.blob, event.data.filename); } // } }); </${"script"}> </body> </html>`; const isIOS = /iPad|iPhone|iPod/.test(navigator.platform) || (navigator.platform === 'MacIntel' && navigator.maxTouchPoints > 1) && !window.MSStream; const iframe = document.getElementById("iframe"); const button = document.getElementById("download"); iframe.setAttribute("srcdoc", iframeHtml); const blob = new Blob(["a message from the iframe"], {type: "text/plain"}); window.addEventListener("message", async event => { //if (event.origin === window.location.origin) { //} }); button.addEventListener("click", async evt => { if (isIOS) { const reader = new FileReader(); const promise = new Promise((resolve, reject) => { reader.addEventListener("error", e => reject(e.error)); reader.addEventListener("load", e => resolve(e.target.result)); }); reader.readAsArrayBuffer(blob); let buffer = await promise; iframe.contentWindow.postMessage({type: "downloadBuffer", mimeType: "text/plain", buffer, filename: "hello world.txt"}, "*"); } else { iframe.contentWindow.postMessage({type: "downloadBlob", blob, filename: "hello world.txt"}, "*"); } /* if (window.SharedArrayBuffer) { const srcView = new Uint8Array(buffer); const sharedBuffer = new SharedArrayBuffer(buffer.byteLength); const dstView = new Uint8Array(sharedBuffer); for (var i = srcView.length - 1; i >= 0; i--) { dstView[i] = srcView[i]; } buffer = sharedBuffer; } */ //iframe.contentWindow.postMessage({type: "downloadBlob", blob, filename: "hello world.txt"}, "*"); }); </script> </body> </html>