I have a very strange problem with chrome browser. I try to open files (images and PDFs) in the new popup. For do that I use this function
window.open('data:' + type + ';base64,' + data, '_blank', 'height=300,width=400');
where type and data I get from the server.
So it's work perfectly in Opera, Mozilla, and Edge.
Popup in opera
But in Chrome I get an empty popup window.
Popup in chrome
May be someone knows how can I fix this, or is this chrome bug?
Using instead of this
window.open('data:' + type + ';base64,' + data, '_blank', 'height=300,width=400');
this code
let byteCharacters = atob(file);
let byteNumbers = new Array(byteCharacters.length);
for (let i = 0; i < byteCharacters.length; i++) {
byteNumbers[i] = byteCharacters.charCodeAt(i);
}
let byteArray = new Uint8Array(byteNumbers);
let blob = new Blob([byteArray], {type: contentType});
const fileURL = URL.createObjectURL(blob);
window.open(fileURL, '_blank', 'height=300,width=400');
resolve the problem.
The reason might be Hardware acceleration of chrome.
Try following Douglas answer to disable it, here.
Related
I am currently working on a web page, which gives the possibility of downloading reports in pdf format. The report is generated on the server and the request is made through "Json".
Once the response is obtained, the "pdf" document is displayed in a new browser tab.
The problem I have is that the file name is kept in a base64 format (very very long).
Is there a way to change this file name?
My code that currently works:
$(document).on('click', '.pdfInforme', function (e) {
e.preventDefault();
var data = $(this).attr("ord");
var d = data.split("*");
var ord = d[0];
var pac = d[1];
$('#loading-indicator').show();
var $modal = $(this);
$.ajax({
type: "POST",
url: 'Download.aspx/ServerRequest',
contentType: 'application/json',
dataType: 'json',
data: JSON.stringify({ 'ord': ord }),
success: function (result) {
//pdf
//Is Firefox?
var nav = navigator.userAgent.toLowerCase().indexOf('firefox') > -1;
var byteCharacters = atob(result.d);
var byteNumbers = new Array(byteCharacters.length);
for (var i = 0; i < byteCharacters.length; i++) {
byteNumbers[i] = byteCharacters.charCodeAt(i);
}
var byteArray = new Uint8Array(byteNumbers);
var file = new Blob([byteArray], { type: 'application/pdf;base64' });
const dataURI = result.d;
const blob = file;
const url = URL.createObjectURL(blob);
const blobAnchor = document.createElement('a');
const dataURIAnchor = document.createElement('a');
blobAnchor.download = 'Informe_' + pac + '_' + ord;
dataURIAnchor.download = 'Informe_' + pac + '_' + ord;
blobAnchor.className = 'hidden';
blobAnchor.href = url;
dataURIAnchor.href = dataURI;
document.body.appendChild(blobAnchor);
blobAnchor.onclick = function () {
requestAnimationFrame(function () {
URL.revokeObjectURL(url);
setTimeout(() => blobAnchor.remove(), 300);
});
};
if(nav)
blobAnchor.click();
else
window.open(blobAnchor, '_blank');
$("#downloadzip").remove();
$('#loading-indicator').hide();
},
error: function (req, status, error) {
alert(error);
}
});
});
I have tried: (It only works to change the title of the new tab)
document.title="New File Name";
I found a solution for chrome and edge (very close to solving it):
Download PDF not working with Firefox using Angular 2 and Node
Using this solution i can open a file in a new tab with a short name (eg "0a06ff23-cea1-417b-87ac-ec591315786e") using "blob". But, I still can't modify file name to another default name.
On the other hand, this method does not work in Firefox, where new tab does not even open (it does in Chrome and Edge). In any case, it would be at least a partial solution.
Upgrade
I noticed that Firefox was downloading the file instead of opening it in a new tab. Therefore, I check if it is a firefox browser, and perform different actions for each case. In case of Firefox, the file is downloaded with the default name I chose, and when the browser is Chrome or Edge, the file opens in a new tab with a name similar to "0a06ff23-cea1-417b-87ac- ec591315786e". It is tested on Android and Apple, and in both cases the possibility of downloading the file is given and then it opens automatically.
I have a blob created with a base64, and I need to make this data downloadable as a pdf.
I created this snippet:
var blob = new Blob([byte]);
var link = document.createElement('a');
link.href = window.URL.createObjectURL(blob);
link.target = '_blank';
var fileName = name + '.pdf';
link.download = fileName;
link.click();
It works on all the browsers, except safari mobile on iOS.
The file gets actually downloaded, but its name is "unknown", then it can't be open since the extension gets lost.
The problem is that the download attribute lacks support on this browser and IE.
There are a lot of workarounds for IE, but I didn't find any for Safari/iOS.
Do you know how can I download a blob got from a base64 (no XHR involved) in this browser?
Thank you
I need to make this data downloadable as a pdf (...) in safari iOS
SHORT ANSWER: you can't. Due this bug is impossible to download the file on safari iOS
The alternative is to open the file on the browser with the proper mime type, so it can show its content (and the user can then manually download it if needed).
Make sure to pass mime type when creating the Blob. reference
var blob = new Blob([byte], {type: 'application/pdf'});
Lastly, I'd strongly suggest you to use FileSaver.js which that can handle most of the corner cases/multiple browser support for save (or in this case, open) a file in javascript.
As per the below link:-
https://caniuse.com/#feat=download
Safari 13 Beta 3 is released so you can check on the same, whether its working or not?
You can download a blob got from a base64 by using a atob function.
The atob function will decode a base64-encoded string into a new string with a character for each byte of the binary data.
You can save blob locally via FileSaver.js .
You can also check here that would be helpful:-
How to open Blob URL on Chrome iOS
This is something I have tried in my project and it is working for me.
import "./styles.css";
var pdfData =
"JVBERi0xLjcKCjEgMCBvYmogICUgZW50cnkgcG9pbnQKPDwKICAvVHlwZSAvQ2F0YWxvZwog" +
"IC9QYWdlcyAyIDAgUgo+PgplbmRvYmoKCjIgMCBvYmoKPDwKICAvVHlwZSAvUGFnZXMKICAv" +
"TWVkaWFCb3ggWyAwIDAgMjAwIDIwMCBdCiAgL0NvdW50IDEKICAvS2lkcyBbIDMgMCBSIF0K" +
"Pj4KZW5kb2JqCgozIDAgb2JqCjw8CiAgL1R5cGUgL1BhZ2UKICAvUGFyZW50IDIgMCBSCiAg" +
"L1Jlc291cmNlcyA8PAogICAgL0ZvbnQgPDwKICAgICAgL0YxIDQgMCBSIAogICAgPj4KICA+" +
"PgogIC9Db250ZW50cyA1IDAgUgo+PgplbmRvYmoKCjQgMCBvYmoKPDwKICAvVHlwZSAvRm9u" +
"dAogIC9TdWJ0eXBlIC9UeXBlMQogIC9CYXNlRm9udCAvVGltZXMtUm9tYW4KPj4KZW5kb2Jq" +
"Cgo1IDAgb2JqICAlIHBhZ2UgY29udGVudAo8PAogIC9MZW5ndGggNDQKPj4Kc3RyZWFtCkJU" +
"CjcwIDUwIFRECi9GMSAxMiBUZgooSGVsbG8sIHdvcmxkISkgVGoKRVQKZW5kc3RyZWFtCmVu" +
"ZG9iagoKeHJlZgowIDYKMDAwMDAwMDAwMCA2NTUzNSBmIAowMDAwMDAwMDEwIDAwMDAwIG4g" +
"CjAwMDAwMDAwNzkgMDAwMDAgbiAKMDAwMDAwMDE3MyAwMDAwMCBuIAowMDAwMDAwMzAxIDAw" +
"MDAwIG4gCjAwMDAwMDAzODAgMDAwMDAgbiAKdHJhaWxlcgo8PAogIC9TaXplIDYKICAvUm9v" +
"dCAxIDAgUgo+PgpzdGFydHhyZWYKNDkyCiUlRU9G";
let download = () => {
if (pdfData) {
var iOS = /iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream;
var isChrome =
navigator.userAgent.toLowerCase().indexOf("CriOS") > -1 ||
navigator.vendor.toLowerCase().indexOf("google") > -1;
var iOSVersion = [];
if (iOS) {
iOSVersion = navigator.userAgent
.match(/OS [\d_]+/i)[0]
.substr(3)
.split("_")
.map((n) => parseInt(n));
}
var attachmentData = pdfData;
var attachmentName = "Test.pdf";
var contentType = "application/pdf";
var binary = atob(attachmentData.replace(/\s/g, ""));
var len = binary.length;
var buffer = new ArrayBuffer(len);
var view = new Uint8Array(buffer);
for (var i = 0; i < len; i++) {
view[i] = binary.charCodeAt(i);
}
var linkElement = document.createElement("a");
try {
var hrefUrl = "";
var blob = "";
if (iOS && !isChrome && iOSVersion[0] <= 12) {
blob = "data:application/pdf;base64," + pdfData;
hrefUrl = blob;
} else {
if (iOS && !isChrome) {
contentType = "application/octet-stream";
}
blob = new Blob([view], { type: contentType });
hrefUrl = window.URL.createObjectURL(blob);
}
linkElement.setAttribute("href", hrefUrl);
linkElement.setAttribute("target", "_blank");
if ((iOS && (iOSVersion[0] > 12 || isChrome)) || !iOS) {
linkElement.setAttribute("download", attachmentName);
}
var clickEvent = new MouseEvent("click", {
view: window,
bubbles: true,
cancelable: false
});
linkElement.dispatchEvent(clickEvent);
} catch (ex) {}
}
};
export default function App() {
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<button onClick={download}>Download</button>
</div>
);
}
The "target" attribute in Safari seems to override the "download" attribute. Currently, as to my knowledge, there is no way to solve this. So I think you have to wait for the next Safari version (13) which will be out in a few months.
In new chrome versions I got this error:
Window is not allowed to navigate Top-frame navigations to data URLs
The image looks like that (contains data in the url):
data:image/png;base64,/9j/4AAQSkZJRgABAQAASABIAAD/4QBYRXhpZgAA...
I really need to open it in a new tab. The iFrame solution isn't relevant
A javascript solution:
var newTab = window.open();
newTab.document.body.innerHTML = '<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg==" width="100px" height="100px">';
There's a lot of ways that you can change the way window.open() behaves, check out the documentation. It also shouldn't be hard to create some css/html that will mimic the way Chrome displays images in new tabs. The ability to load data: URLs was removed for security reasons, so you're out of luck if you're looking for a way to do that.
You can use this function to open any base 64 data URI in a new tab:
function openBase64InNewTab (data, mimeType) {
var byteCharacters = atob(data);
var byteNumbers = new Array(byteCharacters.length);
for (var i = 0; i < byteCharacters.length; i++) {
byteNumbers[i] = byteCharacters.charCodeAt(i);
}
var byteArray = new Uint8Array(byteNumbers);
var file = new Blob([byteArray], { type: mimeType + ';base64' });
var fileURL = URL.createObjectURL(file);
window.open(fileURL);
}
In your case with the image, you'd use it like this:
openBase64InNewTab('YOUR_BASE64_DATA', 'image/png');
url adress bar is limited for chars. You can only show "data:image/png;base64,.." string on page Or..
save it with a tag with attribute like download="iLiveCats.jpg"
Your code will be like this: download id
I have recently started using Bootstrap Table and the export plugin for it. A problem I came across is that the export plugin doesn't work for IE, because the files are output using Data URI, which IE doesn't support (I think I read that IE 11 supports it, but no one in my organization uses IE 11, of course.).
The only file types I am interested in exporting are Microsoft office types (Word, Excel) and PDFs.
I have created a functioning workaround for the MS files.
if (supportsDataUriNavigation())
window.open('data:application/vnd.ms-' + defaults.type + ';filename=exportData.doc;' + base64data);
else {
var iframe = document.getElementById("dataFrame");
iframe = iframe.contentWindow || iframe.contentDocument;
iframe.document.open("text/html", "replace");
iframe.document.write(excelFile);
iframe.document.close();
iframe.focus();
iframe.document.execCommand("SaveAs", true, defaults.fileName + fileExtension);
}
In this check, if the browser is IE, then I use the code I found here. This works great for the MS file types, but when I try to do the same for the PDF file, it tries to save as a .htm file. This file is blank. If I replace the fileExtension variable with .pdf in my code, the SaveAs window will not display when I click to export. There are no javascript errors.
I set the src attribute of an embed tag to a string that is returned by the plugin javascript, and it looks like so: 'application/pdf;base64,' + Base64.encode(buffer)
Anyone know of any solution/workaround?
I know this is very old question, but I found the solution and I want to share anyone who has the same problem. You can see the demo here :
https://jsfiddle.net/quangminh_ln/hy36tnt6/
'use strict';
var data = "...Your PDF base64 string...";
var fileName = "your_file_name";
if (window.navigator && window.navigator.msSaveOrOpenBlob) { // IE workaround
var byteCharacters = atob(data);
var byteNumbers = new Array(byteCharacters.length);
for (var i = 0; i < byteCharacters.length; i++) {
byteNumbers[i] = byteCharacters.charCodeAt(i);
}
var byteArray = new Uint8Array(byteNumbers);
var blob = new Blob([byteArray], {type: 'application/pdf'});
window.navigator.msSaveOrOpenBlob(blob, fileName);
}
else { // much easier if not IE
window.open("data:application/pdf;base64, " + data, '', "height=600,width=800");
}
The link that I saw for my solution : https://viethoblog.wordpress.com/2016/08/30/loaddisplay-pdf-from-base64-string-bonus-ie-workaround/
For a webbased application we want to be able to let people sign on an Ipad.running IOS
We use a canvas element to draw on and then upload it to an IBM I Service.running net.data
It works fine on chrome and firefox on a pc.
on an ipad in safari or chrome though the request seems to be empty.
I am searching for hours and don’t seem to be able to find out what is wrong with this code.
Does anybody Know Who I Could Fix this?
We are not using jquery by the way.
belowe is part of the code we use
thanks!
j.v.
GUI.Signature.dataURItoBlob = function(dataURI) {
var binary = atob(dataURI.split(',')[1]);;
var array = [];
var content = null;
for(var i = 0; i < binary.length; i++) {
array.push(binary.charCodeAt(i));
}
content= new Uint8Array(array);
return new Blob([content], {type: 'image/jpeg'});
};
GUI.Signature.send = function(){
if(!GUI.Signature.isEnabled()){return;}
var request = new XMLHttpRequest();
var dataURL = GUI.Signature.canvas.toDataURL('image/jpeg', 0.8);
var blob = GUI.Signature.dataURItoBlob(dataURL);
var fd = new FormData(GLOBAL.activeForm);
var fsUri = GLOBAL.activeForm.action.replace("MAIN","UPLOAD");
fd.append("signature", blob);
fd.append("blobName","signature" );
request.open('POST', fsUri, false);
request.send(fd);
};
the problem is indeed appending the Uint8Array tot the Blob object.
Wrapping the Uint8Array in an ArrayBuffer solves the problem
it was answerd here