PDF Blob - Pop up window not showing content - javascript

I have been working on this problem for the last few days. With no luck on trying to display the stream on <embed src> tag, I just tried to display it on a new window.
The new window shows PDF controls only )
Any idea why the content of the pdf is not showing?
CODE:
$http.post('/fetchBlobURL',{myParams}).success(function (data) {
var file = new Blob([data], {type: 'application/pdf'});
var fileURL = URL.createObjectURL(file);
window.open(fileURL);
});

You need to set the responseType to arraybuffer if you would like to create a blob from your response data:
$http.post('/fetchBlobURL',{myParams}, {responseType: 'arraybuffer'})
.success(function (data) {
var file = new Blob([data], {type: 'application/pdf'});
var fileURL = URL.createObjectURL(file);
window.open(fileURL);
});
more information: Sending_and_Receiving_Binary_Data

If you set { responseType: 'blob' }, no need to create Blob on your own. You can simply create url based with response content:
$http({
url: "...",
method: "POST",
responseType: "blob"
}).then(function(response) {
var fileURL = URL.createObjectURL(response.data);
window.open(fileURL);
});

I use AngularJS v1.3.4
HTML:
<button ng-click="downloadPdf()" class="btn btn-primary">download PDF</button>
JS controller:
'use strict';
angular.module('xxxxxxxxApp')
.controller('MathController', function ($scope, MathServicePDF) {
$scope.downloadPdf = function () {
var fileName = "test.pdf";
var a = document.createElement("a");
document.body.appendChild(a);
MathServicePDF.downloadPdf().then(function (result) {
var file = new Blob([result.data], {type: 'application/pdf'});
var fileURL = window.URL.createObjectURL(file);
a.href = fileURL;
a.download = fileName;
a.click();
});
};
});
JS services:
angular.module('xxxxxxxxApp')
.factory('MathServicePDF', function ($http) {
return {
downloadPdf: function () {
return $http.get('api/downloadPDF', { responseType: 'arraybuffer' }).then(function (response) {
return response;
});
}
};
});
Java REST Web Services - Spring MVC:
#RequestMapping(value = "/downloadPDF", method = RequestMethod.GET, produces = "application/pdf")
public ResponseEntity<byte[]> getPDF() {
FileInputStream fileStream;
try {
fileStream = new FileInputStream(new File("C:\\xxxxx\\xxxxxx\\test.pdf"));
byte[] contents = IOUtils.toByteArray(fileStream);
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.parseMediaType("application/pdf"));
String filename = "test.pdf";
headers.setContentDispositionFormData(filename, filename);
ResponseEntity<byte[]> response = new ResponseEntity<byte[]>(contents, headers, HttpStatus.OK);
return response;
} catch (FileNotFoundException e) {
System.err.println(e);
} catch (IOException e) {
System.err.println(e);
}
return null;
}

// I used this code with the fpdf library.
// Este código lo usé con la libreria fpdf.
var datas = json1;
var xhr = new XMLHttpRequest();
xhr.open("POST", "carpeta/archivo.php");
xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xhr.responseType = "blob";
xhr.onload = function () {
if (this.status === 200) {
var blob = new Blob([xhr.response], {type: 'application/pdf'});
const url = window.URL.createObjectURL(blob);
window.open(url,"_blank");
setTimeout(function () {
// For Firefox it is necessary to delay revoking the ObjectURL
window.URL.revokeObjectURL(datas)
, 100
})
}
};
xhr.send("men="+datas);

You are not required to set the response type if your data is a byte array, make sure you convert it to Uint8Array before passing it to blob.
Example:
let byteArray = new Uint8Array(data)
let file = new Blob(
[byteArray],
{type: 'application/pdf'}
)
It works for me.
If your data is not byteArray, make sure to convert it to byteArray and follow above-mentioned steps to make it work.
//For example if your data is base-64 encoded string.
let byteChars = atob(data); //To decrypt data
let dataArray = = new Array(byteChars.length);
for(let i=0; i< byteChars.length; i++){
dataArray[i] = byteChars.charCodeAt(i);
}
let byteArray = new Uint8Array(dataArray)
let file = new Blob(
[byteArray],
{type: 'application/pdf'}
)

I know this is old but since this pointed me in the right direction, I thought I would share what I am doing in case someone else lands here. I am not using Angular btw.
The user can view or download the file. The choice is given with 2 buttons or 2 links
<button type="button" class="btn btn-primary btn-sm show_tooltip download-form" title="Download File" data-formid="{{ #your-id }}" data-forcedownload="1">
<i class="fas fa-file-download"></i>
</button>
<button type="button" class="btn btn-primary btn-sm show_tooltip download-form" title="View File" data-formid="{{ #your-id }}" data-forcedownload="0">
<i class="fas fa-search"></i>
</button>
I am using jQuery with the native plugin for xhr2. This handles the link/buttons
$('.download-form').click(function(event) {
event.preventDefault();
let fid = $(this).data('formid');
let force_download = $(this).data('forcedownload');
$.ajax({
url: '/download',
dataType: 'native',
type: 'POST',
xhrFields: {
responseType: 'blob'
},
data: {
//you can send any parameters via POST here
personID: "{{ #personID }}",
file_record_id: pfid,
file_type: "contract_form",
dept: "your-dept",
file_category: "fcategory",
force_download: force_download
},
success: function(blob, status, xhr){
if (xhr.getResponseHeader('Custom-FileError')>1) {
alertify.error(xhr.getResponseHeader('Custom-ErrorMsg'));
}else{
//I thought this would work when viewing the PDF but it does not.
blob.name = xhr.getResponseHeader('Custom-FileName');
var fileURL = URL.createObjectURL(blob);
if (xhr.getResponseHeader('Custom-ForceDownload')==1) {
window.open(fileURL);
var link=document.createElement('a');
link.href=window.URL.createObjectURL(blob);
link.download=xhr.getResponseHeader('Custom-FileName');
link.click();
}else{
file_modal(fileURL,'Any Title');
}
}
}
})
});
Then, some more javascript for the modal
function file_modal(blob,the_title)
{
let spinner = "<div class='text-center'><i class='fa fa-spinner fa-spin fa-5x fa-fw'></i></div>";
$("#modal_static_label").html('Loading');
$("#modal_static .modal-body").html(spinner);
if (blob.length > 1) {
$("#modal_static").modal("show");
$("#modal_static_label").html(the_title);
$("#modal_static .modal-body").empty().append('<iframe src='+blob+' width="100%" height="500px" style="border:none;"></iframe>');
}else{
$("#modal_static .modal-body").empty().html('File error');
}
$("#modal_static .modal-footer").html('<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>');
}
On the server side you will need to send custom headers like this [PHP]
header("Content-length: $file_size");
header("Custom-FileError: 0");
header("Custom-FileName: ".$this->params['original_filename']);
header("Custom-ForceDownload: ".$this->params['force_download']);
header('Content-Type: '.$web->mime($this->full_path.$this->new_file_name));
readfile($this->full_path.$this->new_file_name);
If the user clicks "view", a modal will display the PDF if they click "download", the download window will show up with the filename of your choosing. I have tested this with PDF files less than 10mb and it works as expected.
I hope someone finds this useful.

I have been struggling for days finally the solution which worked for me is given below. I had to make the window.print() for PDF in new window needs to work.
var xhr = new XMLHttpRequest();
xhr.open('GET', pdfUrl, true);
xhr.responseType = 'blob';
xhr.onload = function(e) {
if (this['status'] == 200) {
var blob = new Blob([this['response']], {type: 'application/pdf'});
var url = URL.createObjectURL(blob);
var printWindow = window.open(url, '', 'width=800,height=500');
printWindow.print()
}
};
xhr.send();
Some notes on loading PDF & printing in a new window.
Loading pdf in a new window via an iframe will work, but the print will not work if url is an external url.
Browser pop ups must be allowed, then only it will work.
If you try to load iframe from external url and try window.print() you will get empty print or elements which excludes iframe. But you can trigger print manually, which will work.

problem is, it is not converted to proper format. Use function "printPreview(binaryPDFData)" to get print preview dialog of binary pdf data.
you can comment script part if you don't want print dialog open.
printPreview = (data, type = 'application/pdf') => {
let blob = null;
blob = this.b64toBlob(data, type);
const blobURL = URL.createObjectURL(blob);
const theWindow = window.open(blobURL);
const theDoc = theWindow.document;
const theScript = document.createElement('script');
function injectThis() {
window.print();
}
theScript.innerHTML = `window.onload = ${injectThis.toString()};`;
theDoc.body.appendChild(theScript);
};
b64toBlob = (content, contentType) => {
contentType = contentType || '';
const sliceSize = 512;
// method which converts base64 to binary
const byteCharacters = window.atob(content);
const byteArrays = [];
for (let offset = 0; offset < byteCharacters.length; offset += sliceSize) {
const slice = byteCharacters.slice(offset, offset + sliceSize);
const byteNumbers = new Array(slice.length);
for (let i = 0; i < slice.length; i++) {
byteNumbers[i] = slice.charCodeAt(i);
}
const byteArray = new Uint8Array(byteNumbers);
byteArrays.push(byteArray);
}
const blob = new Blob(byteArrays, {
type: contentType
}); // statement which creates the blob
return blob;
};

I ended up just downloading my pdf using below code
function downloadPdfDocument(fileName){
var req = new XMLHttpRequest();
req.open("POST", "/pdf/" + fileName, true);
req.responseType = "blob";
fileName += "_" + new Date() + ".pdf";
req.onload = function (event) {
var blob = req.response;
//for IE
if (window.navigator && window.navigator.msSaveOrOpenBlob) {
window.navigator.msSaveOrOpenBlob(blob, fileName);
} else {
var link = document.createElement('a');
link.href = window.URL.createObjectURL(blob);
link.download = fileName;
link.click();
}
};
req.send();
}

Note: this.file should be you base64 file

Related

I am getting error when i am trying to convert HTML to PDF, How can I resolve this?

I convert html data from response to pdf but got the error...my code is
this.httpClient.post("/getreport/1", obj, { responseType: 'arraybuffer' }).subscribe((data) => {
var dd=new Uint8Array(data)
var file = new Blob([dd], { type: 'application/pdf' });
filename = this.report.key + ".pdf";
let $link = document.createElement("a");
let url = URL.createObjectURL(file);
$link.setAttribute("target", "_blank");
$link.setAttribute("href", url);
$link.setAttribute("download", filename);
$link.style.visibility = "hidden";
document.body.appendChild($link);
$link.click();
});
ERROR: FAILED TO LOAD PDF

Convert Blob to File and preview on browser (not download)

I am getting a Blob content from webservice callout and requirement is to display the file in browser.
What I have:
Blob file (fileBlob)
Above blob parameter I get as response and sending same back to javascript method in "callback". I am trying to convert the blob to respective file format and view on browser (I dont want to download unless enduser wants so).
I tried below:
var callback1 = {
onSuccess: function(e){ //e is the blob content I am receiving
alert('Receiving file from SF:---> ' + e);
var file = new File([e], "uploaded_file.pdf", { type: "application/pdf", lastModified: Date.now() });
//document.body.append(file);
//var blob=new Blob([e], {type:"application/pdf"});
var link=document.createElement('a');
//link.href=window.URL.createObjectURL(e);
link.download=file;
link.click();
}, onFailure: function(error){
alert(error);
}
};
Update
Update 2 (after treating response as base64)
Make use of iframe to display pdf file, the function would look like this with blob response and file name.
function openPDF(resData, fileName) {
var ieEDGE = navigator.userAgent.match(/Edge/g);
var ie = navigator.userAgent.match(/.NET/g); // IE 11+
var oldIE = navigator.userAgent.match(/MSIE/g);
var bytes = new Uint8Array(resData); //use this if data is raw bytes else directly pass resData
var blob = new window.Blob([bytes], { type: 'application/pdf' });
if (ie || oldIE || ieEDGE) {
window.navigator.msSaveBlob(blob, fileName);
}
else {
var fileURL = URL.createObjectURL(blob);
var win = window.open();
win.document.write('<iframe src="' + fileURL + '" frameborder="0" style="border:0; top:0px; left:0px; bottom:0px; right:0px; width:100%; height:100%;" allowfullscreen></iframe>')
}
}

How to store base64 data in sql server

I have created a voice recorder in HTML.
first, it will request stream, after allowing request stream it will show two buttons, like "start" and "Stop". After recording it will convert blob URL to base64 data.
Now what I want is, I have a table SQLserver I want to store base64 data in that table. I am creating this web page using ASP .NET MVC. The base64 data is in javascript. I don't know how to connect to the server.
Please help me.
Thanks.
Html Page code:
<body>
<h1> Audio Recorder</h1>
<p> For now it is supported only in Firefox(v25+) and Chrome(v47+)</p>
<div id='gUMArea'>
<div>
Record:
</div>
<button class="btn btn-default mediaAudio" id='gUMbtn'>Request Stream</button>
</div>
<div id='btns'>
<button class="btn btn-default" id='start'>Start</button>
<button class="btn btn-default" id='stop'>Stop</button>
</div>
<div>
<ul class="list-unstyled" id='ul'></ul>
</div>
<script src="https://code.jquery.com/jquery-2.2.0.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
<script src="~/script.js"></script>
</body>
JavaScript Code:
'use strict'
let log = console.log.bind(console),
id = val => document.getElementById(val),
ul = id('ul'),
gUMbtn = id('gUMbtn'),
start = id('start'),
stop = id('stop'),
stream,
recorder,
counter=1,
chunks,
media;
gUMbtn.onclick = e => {
let mv = id('.mediaAudio'),
mediaOptions = {
audio: {
tag: 'audio',
type: 'audio/mpeg',
ext: '.mp3',
gUM: {audio: true}
}
};
media = mediaOptions.audio;
navigator.mediaDevices.getUserMedia(media.gUM).then(_stream => {
stream = _stream;
id('btns').style.display = 'inherit';
start.removeAttribute('disabled');
recorder = new MediaRecorder(stream);
recorder.ondataavailable = e => {
chunks.push(e.data);
if (recorder.state == 'inactive') saveLink()
};
log('got media successfully');
}).catch(log);
}
start.onclick = e => {
start.disabled = true;
stop.removeAttribute('disabled');
chunks=[];
recorder.start();
}
stop.onclick = e => {
stop.disabled = true;
recorder.stop();
start.removeAttribute('disabled');
}
function saveLink() {
let blob = new Blob(chunks, { type: media.type })
;
var reader = new window.FileReader();
reader.readAsDataURL(blob);
reader.onloadend = function () {
var base64data = reader.result;
console.log(base64data.substr(base64data.indexOf(',') + 1));
alert(base64data.substr(base64data.indexOf(',') + 1));
}
}
Now it have base64 data in base64data variable, I want to store this variable sql server.
Regards.
Your solution has 2 parts:
Getting a blob out of the blob url
Sending that blob to the server
For first part you can use "Fake ajax" technique just pass blob url (url of download.ogg) as the url of your ajax
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function(){
if (this.readyState == 4 && this.status == 200){
var result = this.response
}
}
xhr.open('GET', 'blob:http://example.com/bbdaabf8-ddf2-40d3-975d-ade742417c71');
xhr.responseType = 'blob';
xhr.send();
After ajax completes result will hold a blob now you just send it to ther server using this answer

Downloading or rendering on an Iframe depending on app Logic in Angular JS

I have an angular JS app on which I download a pdf file and then create a blob from it. Like this:
vm.fileData = new ApiDownloadFile({fileId: 1});
return vm.fileData.$query()
.then(function(response) {
try{
console.log("Try..." + new Date());
$log.log(response);
var arrayBufferView = new Uint8Array(response.Body.data);
$log.log(arrayBufferView);
var file = new Blob( [arrayBufferView], {type: response.ContentType});
var link = document.createElement('a');
link.href = window.URL.createObjectURL(file);
link.download = response.fileName;
link.click();
console.log("After..." + new Date());
console.log("GENERATED LINK: "+link.href);
//PDFObject.embed(link.href, "#my-container");
}
catch(e) {
console.log("Execption...");
// TypeError old chrome and FF
window.BlobBuilder = window.BlobBuilder ||
window.WebKitBlobBuilder ||
window.MozBlobBuilder ||
window.MSBlobBuilder;
if (e.name == 'TypeError' && window.BlobBuilder) {
var bb = new BlobBuilder();
bb.append(response.Body.data);
var file = bb.getBlob("image/jpeg");
var link = document.createElement('a');
link.href = window.URL.createObjectURL(file);
link.download = "1.jpg";
//link.click();
}
else if (e.name == "InvalidStateError") {
// InvalidStateError (tested on FF13 WinXP)
var jpeg = new Blob(response.Body.data, {type: "image/jpeg"});
}
else {
// We're screwed, blob constructor unsupported entirely
}
}
},function(err) {
$log.log(err);
});
};
I can donwload the file easily by creating an 'a' element and then clicking it. However I would like to be able to either download it on the browser or render it on an Iframe I have in my view. The logic should be something like this:
if download == true:
create the <a> element and click it to download file.
else:
render the pdf on an iframe and don´t download on browser.
However I´m not able to get the blob URL to be rendered on the Iframe. I´m using PDFObject to visualize the PDF. Can anyone help me achieve this?
Do this in your page
<iframe ng-if="IframeManager.Url" ng-src="{{ IframeManager.Url }}"></iframe>
Then in your controller add
$scope.Download = true;
$scope.IframeManager = {
Show: function (url) {
$scope.IframeManager.Url = url;
},
Hide: function () {
$scope.IframeManager.Url = null;
}
};
So if you want to show the file you do your preview routine blob conversion and get the url
if ($scope.Download) {
var link = document.createElement('a');
link.href = window.URL.createObjectURL(file);
link.download = response.fileName;
link.click();
console.log("After..." + new Date());
console.log("GENERATED LINK: "+link.href);
} else {
$scope.IframeManager.Show(window.URL.createObjectURL(file));
}

replace XMLHttpRequest in javascript

I used to read my local files using XMLHttpRequest.
function getData(fileName)
{
var filePath = fileName;
xmlhttp = new XMLHttpRequest();
xmlhttp.open("GET", filePath, false);
xmlhttp.send(null);
var fileContent = xmlhttp.responseText;
var tempArr = csv2Arr(fileContent);
var returnLabelArr = tempArr[0].toString().split(',');
tempArr.shift();
var returnDataArr = tempArr;
return { 'dataArr' : returnDataArr, 'labelArr' : returnLabelArr };
}
fileName starts with "C://..." and my program works on browser with address "file:///...".
But, without "--allow-file-access-from-files" tag, my code doesn't work on Chrome. And also it doesn't work on IE and Firefox without changing some security options.
So, I tried to jquery API like this,
function getData(fileName)
{
var filePath = fileName;
var fileContent;
$.ajax({
type: "GET",
url: filePath
})
.done(function(data) {
alert(data);
fileContent = data;
});
var tempArr = csv2Arr(fileContent);
var returnLabelArr = tempArr[0].toString().split(',');
tempArr.shift();
var returnDataArr = tempArr;
return { 'dataArr' : returnDataArr, 'labelArr' : returnLabelArr };
}
The Problem also occurs. I think Same-origin policy prevents it.
Can anyone give me some suggestions for me to access local files without changing security options? Should I use some plug-ins to solve this?
Please let me know.
Thank you.
If you can use <input type="file"> to select files, then the solution is:
HTML:
<form action="">
<input type="file" id="file-input" multiple="multiple" accept="image/jpeg" />
</form>
JS:
var fileInput = document.querySelector('#file-input');
fileInput.addEventListener('change', function(event) {
var files = fileInput.files;
if (files.lenght == 0) {
return;
}
for(var i = 0; i < files.length; i++) {
readFile(files[i]);
}
fileInput.value = "";
}, false);
var readFile= function(file) {
var reader = new FileReader();
reader.onload = function(e) {
var dataUrl = e.target.result;
// now, load the data into some element
// if this is image, you can do this:
var image = new Image();
image.src = dataUrl;
document.body.appendChild(image);
};
reader.readAsDataURL(file);
};
Also, discover the FileReader API to find out, how you can use it otherwise, as it has more methods to read data.

Categories

Resources