How to to convert string response to ArrayBuffer? - javascript

From server I am getting the pdf response as string format, Now on client side, I want to convert it into ArrayBuffer, So that we can change again in pdf.
I am converting it into pdf, like following, but is not pdf is getting corrupted.
function str2ab(str) {
var buf = new ArrayBuffer(str.length*2); // 2 bytes for each char
var bufView = new Uint8Array(buf);
for (var i=0, strLen=str.length; i < strLen; i++) {
bufView[i] = str.charCodeAt(i);
}
return buf;
}
Above function I got from stackover flow, I change Uint16Array to Uint8Array, pdfkit uses utf-8 uncode formate..
service.getAddress(reqData).then(function(response){
if(response.data.error ===1){
toastr.error(response.data.message ,"Unsuccessful");
}else{
var uintStr = str2ab(response.data);
var file = new Blob([uintStr], {
type : 'application/pdf'
});
//trick to download store a file having its URL
var fileURL = URL.createObjectURL(file);
var a = document.createElement('a');
a.href = fileURL;
a.target = '_blank';
a.download = envelopeObj.customer_name+'_'+ 'envId_'+envelopeObj.envelope_id+'.pdf';
document.body.appendChild(a);
a.click();
}
});
To using pdf kit to convert it into string format.
add_str = render_to_string(address_template_path , {"address_dict": address_dict})
pdfkit.from_string(add_str, file_location)
address_pdf = open(file_location)
response = HttpResponse(address_pdf.read(), content_type='application/pdf') # Generates the response as pdf response.
response['Content-Disposition'] = 'inline;filename= %s' % envelope_id

Related

How to create zip from base64 zip content received from http response in JavaScript

what I want to achieve is I have an API which is returning a zipped content as base64 content, I want to consume that API in JavaScript and using that content again want to create zip file and download that to clients system
If you already have the base64 content from the API you can download that as zip file like below.
var byteCharacters = atob(base64);
var byteNumbers = new Array(byteCharacters.length);
for (let i = 0; i < byteCharacters.length; i++) {
byteNumbers[i] = byteCharacters.charCodeAt(i);
}
var byteArray = new Uint8Array(byteNumbers);
var blob = new Blob([byteArray],{type:'application/zip'});
var blobUrl = URL.createObjectURL(blob);
var link = document.createElement('a');
link.href = blobUrl;
link.setAttribute('download', 'reports.zip');
document.body.appendChild(link);
link.click();

How to create a xls file from base64 data in javascript

I get a response that is a base64 string, i need to convert it to xls but i can't do it
This is what i have, the file is created, but at time of opening is corrupted
const str = 'UEsDBBQACAgIABNgWk8AAAAAAAAAAAAAAAAfAAAAUmVzdWx0YWRvQ2FyZ2FUaXR1bG9zMTA2NDk3Lnhsc+1XTWhTQRD+9uWladXGpNb/Wp6pok3TooI/KJrGGDGQNpKmKhqJ/XloMDaSRtST8e+mIHjx4MWjF38uelDE3jwIih4ET9W7qKjgQfucnfde86NVC/4gdsLu7H47szM7O2938/iRd/TKzQUvUEUb4MCYUYeaMkyUC3gAp4WNGYYhISlrTNE/RQnk6FeAhgiGiOdxvDoVvktz4BT2XOLH4uN5dN9ltneS9TwOop/9ODgp25IaoIjy9fys3iXXpE19kxRU5vyvmfXP2a+rpQ+5xomnnoeuEMxv+AXNekMd4blfUknhMGqBo3p/Nrc/M6D9CdrMPvQJ6cNGSpjL1HdjPvvUwPUsrq+zxF1TjkYOCLdIrb/Xso5XJ7BL6WS581z7uHZTLXCbdZ4zshKz8UBG8sQFK4mdCOUzfdlfONCsNlFzLjmxxNcSaGlZkW7dkFpud1Ktzepiin5TxfiehD64t1LIBxcWlYQ6VlTOQ30ptYw2zFctVTWbJboWfqwC0hL3a7Zlq5tabhm2AV+7j0c706TagVb6kWq5XqVSlUYQAayvNGb6VmmPXSszGQyWpliDNtqvklFb/yvlKs1RNPJ2fDC0svy/r0lc2Pj7n8OVSeL4D3FBd0qJ7Hi2mfIfq/HWCfDABLh/ArzuK/yiosJTdBiSe4s1zBuKKvNZRRdzFMG8seg09vG5cBZevJYPHJoxoQ8fyRb6BnPnoJIJgWuCuTqXvjL70vuEC5B3ilVCifC26I44tSI9yVCyt2c6sCXSE05Et4ej8e56YGs8Fo1r4Xh3MhGPkcvJaLI3Fm+PdHWFtFgkGQ1HQ+1dkVike0tkd8exQ1k/ibwqHMnmND2rDxTy74YyAzktr+/PDBfy5JymH8sUcsN9h/Shgu6gM231GgPTyMNeWsYM8moa7OPegzv1D10jMI/76Urj+DYpFk+T4/V8TM6gehAzue3lcQ/N+enq2ydd/duDacb9jLdxfYqRorwwLFoqAwwDJ2lkRJW2ZlM5zdJnuL5CZ5UgK4J/CgIiYIV1NGhzgV4aoVkVd5mntE7UKh5uq7BuPzGTMVGFfeYIgNYiyewJ6onxnsLrtHsO6jmsnmA9uQ4H2ResZ9KboDkudZ3j0lJXxvYZeXyZeCPWYZPSgFv8nu5EiRZZVlB6X0vjv/fVVyJhhdLBwTLf9DVWGtdy9pv+UPpyElHiwm0FUYbdC3kfy9sYsLd2DhW65zCPynwqC6gspNLEywWaYf5nmKK/T3Ifyvd/zMKm9uf/oC9QSwcILi4fO7UDAAAAEAAAUEsBAhQAFAAICAgAE2BaTy4uHzu1AwAAABAAAB8AAAAAAAAAAAAAAAAAAAAAAFJlc3VsdGFkb0NhcmdhVGl0dWxvczEwNjQ5Ny54bHNQSwUGAAAAAAEAAQBNAAAAAgQAAAAA';
const contentType = 'application/vnd.ms-excel';
const byteCharacters = atob(str);
const byteNumbers = new Array(byteCharacters.length);
for (let i = 0; i < byteCharacters.length; i++) {
byteNumbers[i] = byteCharacters.charCodeAt(i);
}
const byteArray = new Uint8Array(byteNumbers);
const blob = new Blob([byteArray], {type: contentType});
const objectURL = window.URL.createObjectURL(blob);
const anchor = document.createElement('a');
anchor.href = objectURL;
anchor.download = name;
anchor.click();
URL.revokeObjectURL(objectURL);
As a test I tried with a image png and works correctly
From this i just change the str to another base64 string and the contentType to 'image/png'
const str = 'iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg=='
const contentType='image/png'

Getting corrupted file while exporting .xls file using java/javascript and apache POI

I am trying to downlaod a .xls file in browser from a web application. Below is the code for the same.
try(FileInputStream inputStream = new FileInputStream("C:\\Users\\Desktop\\Book1.xls")){
response.setContentType("application/vnd.ms-excel");
//response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
response.setHeader("Content-Disposition", "attachment; filename=Book1.xls");
outputStream = response.getOutputStream();
byte[] buffer = new byte[BUFFERSIZE];
int bytesRead = -1;
while ((bytesRead = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, bytesRead);
}
}
Below is the javascript code used to download the file content.
success: function(response, status, xhr) {
let type = xhr.getResponseHeader('Content-Type');
let blob = new Blob([response], { type: type });
if (typeof window.navigator.msSaveBlob !== 'undefined') {
// IE workaround for "HTML7007: One or more blob URLs were revoked by closing the blob for which they were created.
//These URLs will no longer resolve as the data backing the URL has been freed."
window.navigator.msSaveBlob(blob, filename);
} else {
let URL = window.URL || window.webkitURL;
let downloadUrl = URL.createObjectURL(blob);
if (filename) {
// use HTML5 a[download] attribute to specify filename
let a = document.createElement("a");
// safari doesn't support this yet
if (typeof a.download === 'undefined') {
window.location = downloadUrl;
} else {
a.href = downloadUrl;
a.download = filename;
document.body.appendChild(a);
a.click();
}
} else {
window.location = downloadUrl;
}
setTimeout(function () {
URL.revokeObjectURL(downloadUrl);
}, 100); // cleanup
}
}
I am able to download the file, but downloaded file content is not in readble format. If it is csv file I am able to see content in my javascript response object where as for .xls file javascript response object contains unreadable formatted data.
Can somebody help me here?
Posting this solution if anyone else faces the same issue, I resolved this issue via base64 encoding the byte array to a string as below.
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
workbook.write(outputStream);
String res = Base64.getEncoder().encodeToString(outputStream.toByteArray());
In javascript I decoded that string using base64ToBlob method from below link
https://stackoverflow.com/a/20151856/2011294
function base64toBlob(base64Data, contentType) {
contentType = contentType || '';
var sliceSize = 1024;
var byteCharacters = atob(base64Data);
var bytesLength = byteCharacters.length;
var slicesCount = Math.ceil(bytesLength / sliceSize);
var byteArrays = new Array(slicesCount);
for (var sliceIndex = 0; sliceIndex < slicesCount; ++sliceIndex) {
var begin = sliceIndex * sliceSize;
var end = Math.min(begin + sliceSize, bytesLength);
var bytes = new Array(end - begin);
for (var offset = begin, i = 0; offset < end; ++i, ++offset) {
bytes[i] = byteCharacters[offset].charCodeAt(0);
}
byteArrays[sliceIndex] = new Uint8Array(bytes);
}
return new Blob(byteArrays, { type: contentType });
}

How to save .xlsx data to file as a blob

I have a similar question to this question(Javascript: Exporting large text/csv file crashes Google Chrome):
I am trying to save the data created by excelbuilder.js's EB.createFile() function. If I put the file data as the href attribute value of a link, it works. However, when data is big, it crashes Chrome browser. Code are like this:
//generate a temp <a /> tag
var link = document.createElement("a");
link.href = 'data:application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;base64,' + encodeURIComponent(data);
link.style = "visibility:hidden";
link.download = fileName;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
My code to create the data using excelbuilder.js is like follows:
var artistWorkbook = EB.createWorkbook();
var albumList = artistWorkbook.createWorksheet({name: 'Album List'});
albumList.setData(originalData);
artistWorkbook.addWorksheet(albumList);
var data = EB.createFile(artistWorkbook);
As suggested by the answer of the similar question (Javascript: Exporting large text/csv file crashes Google Chrome), a blob needs to be created.
My problem is, what is saved in the file isn't a valid Excel file that can be opened by Excel. The code that I use to save the blob is like this:
var blob = new Blob(
[data],
{type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;base64,"}
);
// Programatically create a link and click it:
var a = document.createElement("a");
a.href = URL.createObjectURL(blob);
a.download = fileName;
a.click();
If I replace the [data] in the above code with [Base64.decode(data)], the contents in the file saved looks more like the expected excel data, but still cannot be opened by Excel.
I had the same problem as you. It turns out you need to convert the Excel data file to an ArrayBuffer.
var blob = new Blob([s2ab(atob(data))], {
type: ''
});
href = URL.createObjectURL(blob);
The s2ab (string to array buffer) method (which I got from https://github.com/SheetJS/js-xlsx/blob/master/README.md) is:
function s2ab(s) {
var buf = new ArrayBuffer(s.length);
var view = new Uint8Array(buf);
for (var i=0; i!=s.length; ++i) view[i] = s.charCodeAt(i) & 0xFF;
return buf;
}
The answer above is correct. Please be sure that you have a string data in base64 in the data variable without any prefix or stuff like that just raw data.
Here's what I did on the server side (asp.net mvc core):
string path = Path.Combine(folder, fileName);
Byte[] bytes = System.IO.File.ReadAllBytes(path);
string base64 = Convert.ToBase64String(bytes);
On the client side, I did the following code:
const xhr = new XMLHttpRequest();
xhr.open("GET", url);
xhr.setRequestHeader("Content-Type", "text/plain");
xhr.onload = () => {
var bin = atob(xhr.response);
var ab = s2ab(bin); // from example above
var blob = new Blob([ab], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;' });
var link = document.createElement('a');
link.href = window.URL.createObjectURL(blob);
link.download = 'demo.xlsx';
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
};
xhr.send();
And it works perfectly for me.
I've found a solution worked for me:
const handleDownload = async () => {
const req = await axios({
method: "get",
url: `/companies/${company.id}/data`,
responseType: "blob",
});
var blob = new Blob([req.data], {
type: req.headers["content-type"],
});
const link = document.createElement("a");
link.href = window.URL.createObjectURL(blob);
link.download = `report_${new Date().getTime()}.xlsx`;
link.click();
};
I just point a responseType: "blob"
This works as of: v0.14.0 of https://github.com/SheetJS/js-xlsx
/* generate array buffer */
var wbout = XLSX.write(wb, {type:"array", bookType:'xlsx'});
/* create data URL */
var url = URL.createObjectURL(new Blob([wbout], {type: 'application/octet-stream'}));
/* trigger download with chrome API */
chrome.downloads.download({ url: url, filename: "testsheet.xlsx", saveAs: true });
Here's my implementation using the fetch api. The server endpoint sends a stream of bytes and the client receives a byte array and creates a blob out of it. A .xlsx file will then be generated.
return fetch(fullUrlEndpoint, options)
.then((res) => {
if (!res.ok) {
const responseStatusText = res.statusText
const errorMessage = `${responseStatusText}`
throw new Error(errorMessage);
}
return res.arrayBuffer();
})
.then((ab) => {
// BE endpoint sends a readable stream of bytes
const byteArray = new Uint8Array(ab);
const a = window.document.createElement('a');
a.href = window.URL.createObjectURL(
new Blob([byteArray], {
type:
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
}),
);
a.download = `${fileName}.XLSX`;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
})
.catch(error => {
throw new Error('Error occurred:' + error);
});
Solution for me.
Step: 1
<a onclick="exportAsExcel()">Export to excel</a>
Step: 2
I'm using file-saver lib.
Read more: https://www.npmjs.com/package/file-saver
npm i file-saver
Step: 3
let FileSaver = require('file-saver'); // path to file-saver
function exportAsExcel() {
let dataBlob = '...kAAAAFAAIcmtzaGVldHMvc2hlZXQxLnhtbFBLBQYAAAAACQAJAD8CAADdGAAAAAA='; // If have ; You should be split get blob data only
this.downloadFile(dataBlob);
}
function downloadFile(blobContent){
let blob = new Blob([base64toBlob(blobContent, 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet')], {});
FileSaver.saveAs(blob, 'report.xlsx');
}
function base64toBlob(base64Data, contentType) {
contentType = contentType || '';
let sliceSize = 1024;
let byteCharacters = atob(base64Data);
let bytesLength = byteCharacters.length;
let slicesCount = Math.ceil(bytesLength / sliceSize);
let byteArrays = new Array(slicesCount);
for (let sliceIndex = 0; sliceIndex < slicesCount; ++sliceIndex) {
let begin = sliceIndex * sliceSize;
let end = Math.min(begin + sliceSize, bytesLength);
let bytes = new Array(end - begin);
for (var offset = begin, i = 0; offset < end; ++i, ++offset) {
bytes[i] = byteCharacters[offset].charCodeAt(0);
}
byteArrays[sliceIndex] = new Uint8Array(bytes);
}
return new Blob(byteArrays, { type: contentType });
}
Work for me. ^^
try FileSaver.js library. it might help.
https://github.com/eligrey/FileSaver.js/
This answer depends on both the frontend and backend having a compatible return object, so giving both frontend & backend logic. Make sure backend return data is base64 encoded for the following logic to work.
// Backend code written in nodejs to generate XLS from CSV
import * as XLSX from 'xlsx';
export const convertCsvToExcelBuffer = (csvString: string) => {
const arrayOfArrayCsv = csvString.split("\n").map((row: string) => {
return row.split(",")
});
const wb = XLSX.utils.book_new();
const newWs = XLSX.utils.aoa_to_sheet(arrayOfArrayCsv);
XLSX.utils.book_append_sheet(wb, newWs);
const rawExcel = XLSX.write(wb, { type: 'base64' })
// set res.setHeader('Content-Type', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet')
// to include content type information to frontend.
return rawExcel
}
//frontend logic to get the backend response and download file.
// function from Ron T's answer which gets a string from ArrayBuffer.
const s2ab = (s) => {
var buf = new ArrayBuffer(s.length);
var view = new Uint8Array(buf);
for (var i = 0; i !== s.length; ++i) view[i] = s.charCodeAt(i) & 0xFF;
return buf;
};
const downloadExcelInBrowser = ()=>{
const excelFileData = await backendCall();
const decodedFileData = atob(excelFileData.data);
const arrayBufferContent = s2ab(decodedFileData); // from example above
const blob = new Blob([arrayBufferContent], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;' });
var URL = window.URL || window.webkitURL;
var downloadUrl = URL.createObjectURL(fileBlob);
if (filename) {
// use HTML5 a[download] attribute to specify filename
var a = document.createElement('a');
// safari doesn't support this yet
if (typeof a.download === 'undefined') {
window.location.href = downloadUrl;
} else {
a.href = downloadUrl;
a.download = 'test.xlsx';
document.body.appendChild(a);
a.click();
}
} else {
window.location.href = downloadUrl;
}
}
if you are using typescript then here is a working example of how to convert array to xlsx and download it.
const fileName = "CustomersTemplate";
const fileExtension = ".xlsx";
const fullFileName = fileName.concat(fileExtension);
const workBook : WorkBook = utils.book_new();
const content : WorkSheet = utils.json_to_sheet([{"column 1": "data", "column 2": "data"}]);
utils.book_append_sheet(workBook, content, fileName);
const buffer : any = writeFile(workBook, fullFileName);
const data : Blob = new Blob(buffer, { type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;" });
const url = URL.createObjectURL(data); //some browser may use window.URL
const a = document.createElement("a");
document.body.appendChild(a);
a.href = url;
a.download = fullFileName;
a.click();
setTimeout(() => {
window.URL.revokeObjectURL(url);
document.body.removeChild(a);
}, 0);

Unable to display binary to image

I am trying to get an image from a URL by using Ajax and want to convert this into data URL.
so far I have done following things("ALL DOES NOT WORK :(")
sforce.connection.remoteFunction({
url : newURL,
mimeType: 'text/plain',
requestHeaders: {"responseType": "arraybuffer"},
onSuccess:function(response){
console.log(newURL);
var reader = new FileReader();
reader.onload = function(){
var dataURL = reader.result;
var output = document.getElementById(imageID);
output.src = dataURL;
};
var blob = new Blob([response], {type: "image/png"});
console.log(blob);
reader.readAsDataURL(blob);
}
This above code return data url but that does not display any image(corrupted).
I have done below thing also :
First converted response binary string into array like below
var bytes = new Uint8Array(response.length);
for (var i=0; i<response.length; i++)
bytes[i] = response.charCodeAt(i);
Now I converted above array into base64 like below
function Uint8ToString(u8a){
var CHUNK_SZ = 0x8000;
var c = [];
for (var i=0; i < u8a.length; i+=CHUNK_SZ) {
c.push(String.fromCharCode.apply(null, u8a.subarray(i, i+CHUNK_SZ)));
}
return c.join("");
}
// Usage
var u8 = bytes;
var b64encoded = btoa(Uint8ToString(u8));
make data URI with above base64 like below
var dataurl = 'data:image/png;base64,'+b64encoded;
But nothing is working.
Below is the end point url to get image from
http://featherfiles.aviary.com/2014-10-24/f93707f9c1472f8a/7892b73db1d947adb7bc536d5d03e5c0.png
Please help me as I am not able to understand how to solve this :(
Are you able to get the blob of image correctly? i.e. it's size is that of the image right?
If yes , then you might be just missing this line (the creation of blobUrl from blob)
var blob = new Blob([response], {type: "image/png"});
var blobUrl= URL.createObjectURL(blob); //create blobUrl from blob
console.log(blob);
console.log(blobUrl)
reader.readAsDataURL(blobUrl);

Categories