Open blob objectURL in Chrome - javascript

I want to open a PDF in a new tab in chrome browser (Chrome 56.0.2924.87, Ubuntu 14.04) using window.open(fileObjectURL) in javascript. I am creating the blob from base64 encoded data and do create an objectURL like this:
const fileObjectURL = URL.createObjectURL(fileBlob);
It works fine in latest Firefox browser. But in Chrome I can see that the new tab gets opened but then closed immediately. So I don't get any error in the console etc.
The only way it works in Chrome now is to give the base64 data directly to the window.open(fileBase64Data) function. But I don't like the complete data being set in the url.
Maybe this is a safety issue with Chrome blocking opening of blobs?

The cause is probably adblock extension (I had exactly the same problem).

You must open new window before you put blob url in window:
let newWindow = window.open('/')
Also you can use some another page like /loading, with loading indicator.
Then you need to wait newWindow loading, and you can push url of your blob file in this window:
newWindow.onload = () => {
newWindow.location = URL.createObjectURL(blob);
};
Adblock extension don't block it.
I'm using it with AJAX and ES generators like this:
let openPDF = openFile();
openPDF.next();
axios.get('/pdf', params).then(file => {
openPDF.next(file);
});
function* openFile() {
let newWindow = window.open('/pages/loading');
// get file after .next(file)
let file = yield;
// AJAX query can finish before window loaded,
// So we need to check document.readyState, else listen event
if (newWindow.document.readyState === 'complete') {
openFileHelper(newWindow, file);
} else {
newWindow.onload = () => {
openFileHelper(newWindow, file);
};
}
}
function openFileHelper(newWindow, file) {
let blob = new Blob([file._data], {type: `${file._data.type}`});
newWindow.location = URL.createObjectURL(blob);
}

Work around way to by pass adblocker.
coffeescript & jquery
$object = $("<object>")
$object.css
position: 'fixed'
top: 0
left: 0
bottom: 0
right: 0
width: '100%'
height: '100%'
$object.attr 'type', 'application/pdf'
$object.attr 'data', fileObjectURL
new_window = window.open()
new_window.onload = ->
$(new_window.document.body).append $object

In plain vanilly javascript (because I don't have jquery)
let newWindow = window.open('/file.html');
newWindow.onload = () => {
var blobHtmlElement;
blobHtmlElement = document.createElement('object');
blobHtmlElement.style.position = 'fixed';
blobHtmlElement.style.top = '0';
blobHtmlElement.style.left = '0';
blobHtmlElement.style.bottom = '0';
blobHtmlElement.style.right = '0';
blobHtmlElement.style.width = '100%';
blobHtmlElement.style.height = '100%';
blobHtmlElement.setAttribute('type', 'application/pdf');
blobHtmlElement.setAttribute('data', fileObjectURL);
newWindow.document.title = 'my custom document title';
newWindow.document.body.appendChild(blobHtmlElement);
};
/file.html is an almost empty html file, source:
<!DOCTYPE html>
<html lang="en">
<head>
</head>
<body>
</body>
</html>
Tested in chrome & firefox (on 20/november/2019)

Unfortunately none of the above solutions worked. The new window still gets blocked in production, in development it works. Only Chrome blocks, in Edge it's all fine.

I do not have Ad blocker. Looks like setting the blob type explicitly to application/pdf will solve this issue.
const newBlob = new Blob([blobData], {type: "application/pdf"});

Salaam
blob:http://***.***.***.**/392d72e4-4481-4843-b0d4-a753421c0433
Blobs are not blocked by chrome but are blocked by AdBlock extension
Either:
Pause on this site
Don't run on pages on this site
Or Disable or Remove AdBlock Extension

Related

How to manage Activex events in JS without Object tag

Hi im developing activex control to manage webcam in IE, everything works but i need to refresh the image when a new frame is captures, up to now i display images on click, but i want to listen "Captured frame event" in JS to refresh my html view.
I have seen a lot of samples but all of these are using Object tag in html
<object id="Control" classid="CLSID:id"/>
<script for="Control" event="myEvent()">
alert("hello");
</script>
is there a way to listen activex events using pure JS? using :
Ob = new ActivexObject('PROG.ID');
No, it's not working in purly JavaScript you can only use JScript.
JScript only works in Internet Explorer and there it only works, if the user confirms to execute the scripts, ussualy you use it in an .hta Hyper Text (Markup Language) Application
Example:
<script language="JScript">
"use strict";
function openFile(strFileName) {
var fso = new ActiveXObject("Scripting.FileSystemObject");
var f = fso.OpenTextFile(strFileName, 1);
if (f.AtEndOfStream) {
return;
}
var file = f.ReadAll();
f.close();
return file;
}
function writeFile(filename, content) {
var fso = new ActiveXObject("Scripting.FileSystemObject");
var f = fso.OpenTextFile(filename, 2, true);
f.Write(content);
f.Close();
}
</script>
<script language="javascript">
"use strict";
var native_db;
function init() {
var file = openFile("./Natives.json");
native_db = JSON.parse(file);
displayNamespaces();
};
I also would have as alternate an example how it works in modern Browsers, if it helps you out there:
<video id="webcam"></video>
<input type="button" value="activate webcam" onclick="test()">
<script>
function test() {
navigator.mediaDevices.getUserMedia({video: true, audio: true}).then((stream) => { // get access to webcam
const videoElement = document.getElementById('webcam');
videoElement.srcObject = stream; // set our stream, to the video element
videoElement.play();
// This creates a Screenshot on click, as you mentioned
videoElement.addEventListener('click', function(event) {
const canvas = document.createElement('canvas');
canvas.width = videoElement.videoWidth;
canvas.height = videoElement.videoHeight;
const context = canvas.getContext('2d');
context.drawImage(videoElement, 0, 0, videoElement.videoWidth, videoElement.videoHeight);
// you could just do this, to display the canvas:
// document.body.appendChild(canvas);
canvas.toBlob(function (blob) { // we automatlicly download the screenshot
const a = document.createElement('a');
a.href = URL.createObjectURL(blob); // creates a Datastream Handle Link in your Browser
a.download = 'screenshot.png'; // the name we have to define here now, since it will not use the url name
document.body.appendChild(a); // some Browsers don't like operating with Events of Objects which aren't on DOM
setTimeout(function() { // so we timeout a ms
a.click(); // trigger the download
URL.revokeObjectURL(a.href); // release the Handle
document.body.removeChild(a); // remove the element again
}, 1);
});
});
}).catch(console.error);
}
</script>
I ended up using timer, when i click enable button in the view i call the method startRecord, in this method i read Activex value every 70 ms, I would rather not use timer but it works.
private async startRecord() {
while (this.banCapturing) {
await new Promise(res => setTimeout(res, 70)); //14 ~ 15 fps
this.foto = this.Ob.imageBase64; //Read Activex Value, DLL is updating imageBase64 on camera event.
}
}

How to Download a PDF file in the background

How do I download a file in the background of a mobile browser without leaving the current page.
I've taken a look at this StackOverflow post: easiest way to open a download window without navigating away from the page
which works for displaying the file( in this case a pdf) in the same window using this code:
var file_path = 'https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf';
var a = document.createElement('A');
a.href = file_path;
a.download = file_path.substr(file_path.lastIndexOf('/') + 1);
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
This works fine if you want to display the PDF immediately in the current window.
However, how can you keep the current view and have the file download/display a dialogue showing a download in progress?
The goal is to not open a new tab or window to keep the user engaged with the current page. I've looked through S/O & on the web but haven't found a solution to this. Thanks for any solutions to this issue.
you can use HTML web worker https://www.w3schools.com/html/html5_webworkers.asp
var w;
function stopWorker() {
w.terminate();
w = undefined;
}
function downloadPDFBackground() {
if (typeof(Worker) !== "undefined") {
if (typeof(w) == "undefined") {
w = new Worker("pdf_workers.js");
}
w.onmessage = function(event) {
var file_path = 'https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf';
var a = document.createElement('A');
a.href = file_path;
a.download = file_path.substr(file_path.lastIndexOf('/') + 1);
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
stopWorker();
};
} else {
document.getElementById("result").innerHTML = "Sorry! No Web Worker support.";
}
}

HTML2Canvas works on desktop but not on mobile. How to fix?

The point of the website is to download an image of a signed consent form. Everything works how I would like on desktop, but it does not work on mobile unfortunately. I tried chrome, brave, firefox, and safari. I either get the image showing but not downloading, or some weird page distortion. How can I adjust the code to fix it?
this is the source code:
https://github.com/jacelecomte/wwvhSigns
The methods that deal with the saving of the image are here:
function finalizeScreenshot() {
html2canvas(document.body).then(function (canvas) {
document.body.appendChild(canvas);
saveScreenshot(canvas);
});
}
function injectScript(uri) {
const document = window.document;
const script = document.createElement("script");
script.setAttribute("src", uri);
//document.body.appendChild(script);
}
function injectHtml2canvas() {
injectScript("//html2canvas.hertzen.com/dist/html2canvas.js");
}
injectScript('./src/html2canvas.js');
injectHtml2canvas();
finalizeScreenshot();
function saveScreenshot(canvas) {
const fileName = "Consent Form";
const link = document.createElement("a");
link.download = fileName + ".png";
//console.log(canvas);
canvas.toBlob(function (blob) {
console.log(blob);
link.href = URL.createObjectURL(blob);
link.click();
});
}
//these 3 functions are run in a row to create and download the screenshot.
injectScript('./src/html2canvas.js');
injectHtml2canvas();
finalizeScreenshot();
Change the viewport just before calling html2canvas, then change it back afterwards. This answer was derived from html2canvas issue fix on github
This should fix it:
1: give your <meta name="viewport"../> an id, like this:
<meta name="viewport" content="width=device-width, initial-scale=1.0" id="viewportMeta" />
revised function
function finalizeScreenshot() {
var vp = document.getElementById("viewportMeta").getAttribute("content");
document.getElementById("viewportMeta").setAttribute("content", "width=800");
html2canvas(document.body).then(function (canvas) {
document.body.appendChild(canvas);
saveScreenshot(canvas);
}).then(function () {
document.getElementById("viewportMeta").setAttribute("content", vp);
}); }
You should also be able to set your own windowWidth setting which should trigger the relevant media queries:
html2canvas( document.body, {
windowWidth: '1280px'
} ).then( function( canvas ) {
document.body.appendChild( canvas );
} );
See the available html2canvas options.

How to save data in local hd with javascript?

I'm using CKEditor to create text in a website that create documents. The problem is the internet connection, the PC is far away from town and it's unstable 3G connection. I already have a routine to save a draft every ten seconds (or the time the user wish to be) in the server for safe - simple task. The problem is that if the internet goes down, the user will have to select - copy the text and try to save it locally with some text editor (maybe Word, that will make a mess).
So I'm wondering if already exists a way of to create a file and download to the local HD without remote server, just the JavaScript and navigator. Also, it might be another way to save the job but keeping CPU on and navigator open, but couldn't find in stack overflow.
I found just one non-standard API FireFox compatible:
Device Storage API
Of course, is not JavaScript standard so I don't know if it's a good idea to use right now.
Any ideas?
[Compatibility Note]
This solution uses <a> attribute download, to save the data in a text file.
This html5 attribute is only supported by Chrome 14+, Firefox 20+ and Opera
15+ on
desktop, none on iOS and all current majors except WebView on Android.
-A workaround for IE 10+ is to not hide/destroy the link generated by clickSave()and ask user to right-click > Save target As…
-No known workaround for Safari.
Also note that data will still be accessible via
localStorage.getItem()
for Firefox 3.5+, Chrome&Safari 4+, Opera 10.5+ and IE 9+ (xhr will
crash IE 8-)
I would do it like so, assuming your actual code saves the data via xhr.
function saveData() {
var xhr = new XMLHttpRequest();
//set a timeout, in ms, to see if we're still connected
xhr.timeout = 2000;
xhr.addEventListener('timeout', localStore, false);
xhr.onreadystatechange = function() {
if (xhr.readyState == 4) {
// not a good news
if (xhr.status !== 200) {
localStore();
}
else{
document.querySelector('#local_alert').style.display = 'none';
}
}
}
//I assume you already have the part where you set the credentials
xhr.open('POST', 'your/url.php');
xhr.send();
}
//Show the link + Store the text in localStorage
function localStore() {
document.querySelector('#local_alert').style.display = 'block';
var userText = document.querySelector('textArea').value;
localStorage.setItem("myAwesomeTextEditor", userText);
}
//provide a link to download a file with txt content
window.URL = window.URL || window.webkitURL;
function clickSave(e) {
var userText = document.querySelector('textArea').value;
var blob = new Blob([userText], {type: 'plain/text'});
var a = document.createElement('a');
a.download = "myAwesomeTextEditor" + (new Date).getTime() + '.txt';
a.href = URL.createObjectURL(blob);
a.style.display = "none";
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
}
setInterval(saveData, 3000);
#local_alert {
display: none;
position: static;
width: 100%;
height: 3em;
background-color: #AAA;
color: #FFF;
padding: 0.5em;
}
body,
html {
margin: 0
}
<div id="local_alert">You're actually offline, please beware your draft is not saved on our server
<button onclick="clickSave()">Save Now</button>
</div>
<textarea></textarea>
Ps: If your user leaves the page without connection, you'll be able to get the text back via localStorage.getItem("myAwesomeTextEditor")
PPs: A more "live" example can be found here (it won't save to server but you've got the rest of the logic working). Try to disconnect , then reconnect.
Try
var editor = document.getElementById("editor");
var saveNow = document.getElementById("save");
function saveFile() {
if (confirm("save editor text")) {
var file = document.createElement("a");
file.download = "saved-file-" + new Date().getTime();
var reader = new FileReader();
reader.onload = function(e) {
file.href = e.target.result;
document.body.appendChild(file);
file.click();
document.body.removeChild(file);
};
reader.readAsDataURL(new Blob([editor.value], {
"type": "text/plain"
}));
}
};
saveNow.addEventListener("click", saveFile, false);
<button id="save">save editor text</button><br />
<textarea id="editor"></textarea>

window.open not working in chrome 6

I am trying to open a location in new window(tab) using window.open. It is not working in chrome. First I tried with window.open(url,name), this did not work, however this works in every other browser. Then I used something like this,
var w = window.open("about:blank");
w.opener = null;
w.document.location = url;
This opens the url in same tab but not in separate tab.
Are you sure your popup is not being blocked? Most popup windows that didn't happen in response to a user event will get blocked. I typed window.open("google.com", "_blank") into the console and I got the blocked window on the url bar
Do it like this
window.open( url, "_blank" );
Remember, the 2nd parameter is analogous to an anchor tag's target attribute.
Try this. Works in IE8, fails in FF when popups are blocked
<html>
<head>
<script type="text/javascript">
if(typeof HTMLElement!='undefined'&&!HTMLElement.prototype.click)
HTMLElement.prototype.click=function(){ // event by Jason Karl Davis
var evt = this.ownerDocument.createEvent('MouseEvents');
evt.initMouseEvent('click', true, true, this.ownerDocument.defaultView, 1, 0, 0, 0, 0, false, false, false, false, 0, null);
this.dispatchEvent(evt);
}
function loadAndClick(url,target) {
var lnk = document.createElement("a");
lnk.href=url;
lnk.target=target||"_blank"
lnk.id="myLink"
lnk.onclick=function() {
var w = window.open(this.href,this.target);
return (w)?false:true;
}
document.body.appendChild(lnk);
document.getElementById('myLink').click();
// lnk.click();
}
window.onload=function() { // or call getURL("javascript:loadAndClick('http://www.google.com')");
loadAndClick("http://www.google.com");
}
</script>
</head>
<body>
</body>
</html>
Create a redirect page (for example Redirect.aspx).
window.open('Redirect.aspx?URL=http://www.google.com', '_blank');
From the Redirect.aspx page, redirect to the URL specified in the QS...
This worked a treat for me with Chrome blocking my new windows.

Categories

Resources