Create json file using blob - javascript

I have written json code in string and i want to send it using xmlhttp as .json file. Is it possible to do it with blob?
var cleanScript = {
'type': 'script',
'api_key': api_key,
'data': data,
'inputs': inputs,
'timeoutSeconds': timeoutSeconds
};
var jsonse = JSON.stringify(cleanScript, null, 2);
Now json to blob?

Try something like this
var cleanScript = {
'type': 'script',
'api_key': api_key,
'data': data,
'inputs': inputs,
'timeoutSeconds': timeoutSeconds
};
var jsonse = JSON.stringify(cleanScript);
var blob = new Blob([jsonse], {type: "application/json"});
var url = URL.createObjectURL(blob);
var a = document.createElement('a');
a.href = url;
a.download = "backup.json";
a.textContent = "Download backup.json";
document.getElementById('json').appendChild(a);
<div id="json"></div>

Try the code below:
var int2ByteArray = function(i, minByteCount) {
var result = [],
buf = code = +i,
offsetCount = 0;
while ((buf = code>>(8 * offsetCount)) || offsetCount < minByteCount) {
buf = buf & 0xFF;
++offsetCount;
result.push(buf);
}
return result.reverse();
};
var ascii2ByteArray = function(s) {
if (!s) return 0;
var result = [];
[].map.call(s, function(c) {
result = result.concat(int2ByteArray((typeof(c)).toLowerCase() == "number" ? c : c.charCodeAt(0)));
});
return result;
};
// You got the blob here, do whatever you want.
var blob = new Blob(new Uint8Array(ascii2ByteArray(jsonse)), {type:"text/json"});
The matrix is to convert a string(stringfied by JSON.stringify) in to a Uint8Array that could be used making a blob.
I happened make something like that before, hope it's useful.

Related

Javascript: How to encrypt a zip file with RSA

I'm using Cryptico to handle RSA encryption for chat but I'm running into trouble trying to encrypt a zip file after construction. I see the constructed file in the console. The console shows an encrypted string of the file but returns blank after decryption in the console.
Note: my decryption method works properly with text and base64
$(document).on("change", "#chatImage", function() {
var rid = $(this).closest(".chat").data("id");
var files = this.files;
var zip = new JSZip();
for (var i = 0; i < files.length; i += 1) {
var file = files[i];
zip.file(file.name, file);
console.log("added", file.name);
// console.log(file);
}
var eImgArray = {};
$.ajax({
url : ajax_object.ajax_url,
type : 'post',
data : {
action: 'get_room_member_keys',
rid : rid,
},
beforeSend: function() {
},
success: function(html) {
var pubKeys = $.parseJSON(html);
$.each( pubKeys, function( key, value ) {
var imgEncrypt = cryptico.encrypt(file, value);
var imgSrc = imgEncrypt.cipher;
eImgArray[key] = imgSrc;
});
var strImgArray = JSON.stringify(eImgArray);
$("#chatFormCont input[name=image_data]").val(strImgArray);
var foo = $("#chatFormCont input[name=image_data]").val();
// console.log(foo);
},
});
zip.generateAsync({type: "blob"}).then(function(content) {
function show_all_images(relpath, file) {
if (file.dir) {
return file.forEach(show_all_images);
}
var img = $("#chatImagePreview");
file.async("blob").then(function(blob) {
var src = window.URL.createObjectURL(blob);
img.attr("src", src);
});
}
new JSZip.loadAsync(content).then(zip => zip.forEach(show_all_images));
});
});

Error when printing PDF file in AngularJS

I am trying to print a PDF file generated through reportViewer in my Web API, but the browser shows an error when tries to open the PDF file.
This is the code inside the controller in my Web API:
// ...generate candidatosDataSet
LocalReport relatorio = new LocalReport();
string rootPath = HttpRuntime.AppDomainAppPath;
relatorio.ReportPath = rootPath + #"\Reports\Report.rdlc";
relatorio.DataSources.Add(new ReportDataSource("Candidatos", candidatosDataSet));
relatorio.Refresh();
byte[] relatorioBytes = ExportUtils.GerarArquivoPDF(relatorio);
response = Request.CreateResponse(HttpStatusCode.OK, relatorioBytes);
response.Content.Headers.ContentDisposition = System.Net.Http.Headers.ContentDispositionHeaderValue.Parse("attachment; filename=relatorio.pdf");
response.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/pdf");
This is how I am generating PDF File through reportViewer
public static byte[] GerarArquivoPDF(LocalReport relatorio)
{
String reportType = "PDF";
String mimeType;
String encoding;
String fileNameExtension;
String deviceInfo;
Warning[] warnings;
string[] streams;
byte[] renderedBytes;
deviceInfo = "<DeviceInfo>" + " <OutputFormat>" + reportType + "</OutputFormat>" + "</DeviceInfo>";
renderedBytes = relatorio.Render(
reportType,
deviceInfo,
out mimeType,
out encoding,
out fileNameExtension,
out streams,
out warnings);
return renderedBytes;
}
Here is my AngularJS service method:
function obterTermoConfirmacaoCandidatura(candidatoId) {
return $http.get(configValues.baseUrl + 'candidato/GetRelatorio',
{
params: { candidatoId: candidatoId },
responseType: 'arraybuffer'
});
}
And this is the code that I am using to print the file on the AngularJS controller:
function imprimirTermoConfirmacaoCandidatura(id) {
CandidatoAPIService.obterTermoConfirmacaoCandidatura(id)
.then(function (response) {
var contentType = response.headers('Content-Type') || "application/octet-stream";
var file = new Blob([response.data], {
type: contentType
});
var fileUrl = URL.createObjectURL(file);
var printWindow = $window.open(fileUrl);
printWindow.print();
}, function (error) {
alert(error.data);
});
}
The response from Web API was comming as string, with double quotes in beginning and in the end of the response, so the PDF File could not be rendered correctly. Also I converted the response from server to base64, by this method:
function b64toBlob(b64Data, contentType) {
var sliceSize = 512;
b64Data = b64Data.replace(/"/g, '');
b64Data = b64Data.replace(/^[^,]+,/, '');
b64Data = b64Data.replace(/\s/g, '');
var byteCharacters = window.atob(b64Data);
var byteArrays = [];
for (var offset = 0; offset < byteCharacters.length; offset += sliceSize) {
var slice = byteCharacters.slice(offset, offset + sliceSize);
var byteNumbers = new Array(slice.length);
for (var i = 0; i < slice.length; i++) {
byteNumbers[i] = slice.charCodeAt(i);
}
var byteArray = new Uint8Array(byteNumbers);
byteArrays.push(byteArray);
}
var blob = new Blob(byteArrays, { type: contentType });
return blob;
}
And changed the method on AngularJS controller to convert the response do base64:
function imprimirTermoAutorizacaoUsoImagem() {
CandidatoAPIService.obterTermoAutorizacaoUsoImagem()
.then(function (response) {
var contentType = response.headers('Content-Type') || "application/octet-stream";
var file = UtilsService.b64toBlob(response.data, "application/pdf");
var fileUrl = URL.createObjectURL(file);
var printWindow = $window.open(fileUrl);
printWindow.print();
}, function (error) {
alert(error.data);
});
}
And removed the responseType on the AngularJS service:
function obterTermoConfirmacaoCandidatura(candidatoId) {
return $http.get(configValues.baseUrl + 'candidato/GetObterTermoConfirmacaoCandidatura',
{
params: { candidatoId: candidatoId }
});
}

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);

Create a file with data ur

I have something like this.
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAKQAAACkCAYAAAAZtYVBAAAgAElEQ…TFHIWRhe2sii/S5zA+N/ZF6gI+RiSKspPUBiI1UQf9/wDVxYvlSggfZqgAAAABJRU5Erkaa==="
Is there a way to create a file object? with this?
i see the method URL.createObjectURl but it seems like a need to create a blobl object and i dont really know how.
The following function will convert a data URI to a blob.
function dataURIToBlob(dataURI) {
// Split the dataUri up into parts
// data:[<mediatype>][;<charset>],(data)
var parts = /data:([^;]+)(?:;([^,]+))?,(.+)/.exec(dataURI),
mime = parts[1],
charset = parts[2] || 'charset=US-ASCII',
encodedData = parts[3];
var data;
if (charset === 'base64') {
// If base64 convert to a Uint8 clamped array of character codes
var decodedData = atob(encodedData);
data = new Uint8Array(decodedData.length);
for (var i = 0; i < decodedData.length; i++) {
data[i] = decodedData.charCodeAt(i);
}
} else {
data = decodeURIComponent(encodedData);
}
return new Blob([data], {
type: mime
});
}
You can see it working in this snippet which takes a data URI, converts it into a blob, then creates a blob URI that you can use to access the file. A sample image and CSV file is provided.
testData = {};
testData['image/gif'] = 'data:image/gif;base64,R0lGODlhEAAQAMQAAORHHOVSKudfOulrSOp3WOyDZu6QdvCchPGolfO0o/XBs/fNwfjZ0frl3/zy7////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAkAABAALAAAAAAQABAAAAVVICSOZGlCQAosJ6mu7fiyZeKqNKToQGDsM8hBADgUXoGAiqhSvp5QAnQKGIgUhwFUYLCVDFCrKUE1lBavAViFIDlTImbKC5Gm2hB0SlBCBMQiB0UjIQA7';
testData['text/csv'] = 'data:text/csv;charset=utf-8,ID%2CScore%2CAssignee%2CCreated%2CComment%0Aid_value0%2Cscore_value0%2Cassignee_value0%2Ccreated_value0%2Ccomment_value0%0Aid_value1%2Cscore_value1%2Cassignee_value1%2Ccreated_value1%2Ccomment_value1%0Aid_value2%2Cscore_value2%2Cassignee_value2%2Ccreated_value2%2Ccomment_value2%0A';
function dataURIToBlob(dataURI) {
// Split the dataUri up into parts
// data:[<mediatype>][;<charset>],(data)
var parts = /data:([^;]+)(?:;([^,]+))?,(.+)/.exec(dataURI),
mime = parts[1],
charset = parts[2] || 'charset=US-ASCII',
encodedData = parts[3];
var data;
if (charset === 'base64') {
// If base64 convert to a Uint8 clamped array of character codes
var decodedData = atob(encodedData);
data = new Uint8Array(decodedData.length);
for (var i = 0; i < decodedData.length; i++) {
data[i] = decodedData.charCodeAt(i);
}
} else {
data = decodeURIComponent(encodedData);
}
return new Blob([data], {
type: mime
});
}
function createBlobURI() {
var blob = dataURIToBlob(dataURIInput.value);
var blobURI = URL.createObjectURL(blob);
blobURIAnchor.href = blobURI;
blobURIAnchor.innerHTML = blobURI;
blobURIAnchor.style.display = 'block';
blobURIAnchor.download = 'blob.' + blob.type.split('/')[1];
}
function insertTestData(mime) {
dataURIInput.value = testData[mime];
}
insertTestData('image/gif');
<button onclick="insertTestData('image/gif')">Image test</button>
<button onclick="insertTestData('text/csv')">CSV test</button>
<input id="dataURIInput" type="text"/>
<button onclick='createBlobURI()'>Create blob URI</button>
<a id="blobURIAnchor" href="#" style="display:none"></a>

Safari browsers sends blob/datauri as string in Node.js

I am trying to receive the file sent through AJAX. What's happening is that when the file sent using Chrome/Firefox the file goes to req.files but when it was sent using Safari, the file goes to req.params. The application treat the file as a string "[Object blob]". Thanks.
Sending userdata through ajax.
updatePartnerProfile: function(obj){
var parentObj = this;
var target = $(obj.target);
var parent = target.closest('#editPartnerDetailsForm');
var logoImg = parent.find('.cropped');
var companyLogoBase64 = logoImg.find('.croppedImage').attr('src');
var companyLogo = util.dataURItoBlob(companyLogoBase64);
var userData = new FormData();
userData.append('token', parentObj.token);
userData.append('companyLogo', companyLogo);
$.ajax({
type: 'POST',
url: parentObj.serverUrl + 'api/admin/update/organization/' + parentObj.partnerId,
processData: false,
contentType: false,
cache: false,
data: userData,
success: function(data){
//todo
}
},
error: function(err){
console.log(err);
}
});
},
dataURItoBlob : function(dataURI) {
// convert base64/URLEncoded data component to raw binary data held in a string
if (!_.isUndefined(dataURI)){
var byteString;
if (dataURI.split(',')[0].indexOf('base64') >= 0)
byteString = atob(dataURI.split(',')[1]);
else
byteString = unescape(dataURI.split(',')[1]);
// separate out the mime component
var mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0]
// write the bytes of the string to a typed array
var ia = new Uint8Array(byteString.length);
for (var i = 0; i < byteString.length; i++) {
ia[i] = byteString.charCodeAt(i);
}
return new Blob([ia], {type:mimeString});
} else {
return null;
}
}
Am I missing something in the code?
Well, as per this question, you need to be using the buffer property of ia, not just [ia]. Instead of
return new Blob([ia], {type:mimeString});
try
return new Blob([ia.buffer], {type:mimeString});

Categories