I am receiving json file and image from backend with multipart/form-data and I have to parse it to frontend.
--47f5d03f-8473-428e-a4e7-11e2a0710dc2
�PNG
gAMA���\#�!:����O-Z�h���c�}�Յ��+.���* (etc with this data)
--47f5d03f-8473-428e-a4e7-11e2a0710dc2
{"CustomerId":"123","Title":"This is title","Name":"This is name"}
--47f5d03f-8473-428e-a4e7-11e2a0710dc2--
Json is parsed perfectly, but I have a problem with creating image.
But Blob is always giving me an error when I try to use it for creating image element.
This is how i tried to do this.
API.post(`api/endpoint`, data).then((resp) => {
const boundIndex = resp.headers['content-type'].indexOf('boundary="') + 'boundary='.length;
const contentType = resp.headers['content-type']
const bound = contentType.slice(boundIndex,contentType.length);
const boundary = '--' + bound.slice(1, bound.length - 1);
const splitedResponseData = resp.data.split(boundary);
const jsonResponse = JSON.parse(splitedResponseData[2]);
const blob = new Blob([splitedResponseData[1]], { type: 'image/png' });
const blob1 = new Blob([stringToUint(splitedResponseData[1])], { type: 'image/png' });
Blob1 is using function stringToUint() to convert string to Uint8Array.
function stringToUint(stringData) {
const string1 = btoa(unescape(encodeURIComponent(stringData))),
charList = string1.split(''),
uintArray = [];
for (let i = 0; i < charList.length; i++)
{
uintArray.push(charList[i].charCodeAt(0));
}
return new Uint8Array(uintArray);
}
Am I doing something wrong or is there another way I can take a picture based on the data I get?
Related
I'm using CloudFlare service workers and I want to fetch an image and then generate a base64 representation of it.
So something like this:
const res = await fetch('https://cdn.cnn.com/cnnnext/dam/assets/211010073527-tyson-fury-exlarge-169.jpg')
const blob = await res.blob();
console.log(blob)
console.log(btoa(blob))
this of course doesn't work, any ideas how to get this resolved?
complete worker script with cloudflare using btao
addEventListener('fetch', event => {
event.respondWith(handleRequest(event.request))
})
const imageUrl =
'https://upload.wikimedia.org/wikipedia/commons/thumb/7/72/' +
'Cat_playing_with_a_lizard.jpg/1200px-Cat_playing_with_a_lizard.jpg';
function base64Encode (buf) {
let string = '';
(new Uint8Array(buf)).forEach(
(byte) => { string += String.fromCharCode(byte) }
)
return btoa(string)
}
function base64Decode (string) {
string = atob(string);
const
length = string.length,
buf = new ArrayBuffer(length),
bufView = new Uint8Array(buf);
for (var i = 0; i < length; i++) { bufView[i] = string.charCodeAt(i) }
return buf
}
async function handleRequest(request) {
const
upstreamResponse = await fetch(imageUrl),
text = base64Encode(await upstreamResponse.arrayBuffer()),
bin = base64Decode(text);
return new Response(bin, {status: 200, headers: {
'Content-type': upstreamResponse.headers.get('Content-type')
}})
}
can refer this discussion as well
I tried to convert a base64 string generated from pdf file using FileReader.readAsDataURL() to its original format.In NodeJS I did it like this and it was able generated the pdf to its initial state.
filebuffer = "data:application/pdf;base64,JVBERi0xLjQKJSDi48/..........."
let base64file = fileBuffer.split(';base64,').pop();
fs.writeFileSync('download.pdf',base64file,{encoding:'base64'},function(err){
if(err === null){
console.log("file created");
return;
}
else{
console.log(err);
return;
}
})
But i tried to do it in HTML + Javascript in this way.But in this way , pdf was empty/no letter wasn't in it
let stringval = "data:application/pdf;base64,JVBERi0xLjQKJSDi48/..........."
let encodedString = stringval.split(';base64,').pop();
let data = atob(encodedString);
let blob = new Blob([data]);
// //if you need a literal File object
let file = new File([blob], "filename");
link.href = URL.createObjectURL(file);
link.download = 'filename';
I was Capturing file and converting to base64 string in this way:
captureFile: function () {
event.preventDefault();
const file = event.target.files[0];
$("#labelinput1").html(file.name);
const reader = new window.FileReader();
reader.readAsDataURL(file);
reader.onloadend = () => {
var x = reader.result.toString();
App.buffer2 = x;
console.log("buffer", App.buffer);
};}
Then after clicking a button , I added the buffer to IPFS node
addfile: async function () {
if (App.buffer2 === null) return;
App.node = await window.Ipfs.create()
App.node.add(App.buffer2, function (errx, resipfs) {
if (errx === null) {
console.log(resipfs[0].hash);
App.buffer2 = null;
return App.showInfo(resipfs[0].hash);
}
else {
return App.showError(errx.message.toString() + errx.stack.toString());
}
});
}
using the IPFS HASH i can get back the base64 encoded string , I retrieved this string in this way:
ipfsfiledownload: async function () {
var filebuffer = await App.node.cat(hashtext);
var stringval = filebuffer.toString();
//convert this string to main file
}
I used Truffle Petshop and write those functions in top of it. Here is a IPFS hash QmfSefUiwjV44hpfnHyUngGATyHm9M4vN3PzF1mpe59Nn1. you can try out this Hash value in nodejs with this code
const IPFS = require('ipfs');
const fs = require('fs');
const main = async() => {
const node = await IPFS.create()
var fileBuffer = await
node.cat('QmfSefUiwjV44hpfnHyUngGATyHm9M4vN3PzF1mpe59Nn1')
fileBuffer = fileBuffer.toString()
let base64file = fileBuffer.split(';base64,').pop();
fs.writeFileSync('download.pdf',base64file, {encoding:'base64'},function(err){
if(err === null){
console.log("file created");
return;
}
else{
console.log(err);
return;
}
})
}
main()
You can find the full code here.
What I am doing wrong and how to solve it?
After converting the base64 string using atob() , I converted it to Uint8Array Then created the blob and file . It seems to work now ..
Here is the full code :
ipfsfiledownload: async function () {
var hashtext = document.getElementById("id_ipfshash").value //getting the IPFS HASH
var link = document.getElementById("downloadLink");
if (hashtext === null) return
var filebuffer = await App.node.cat(hashtext); //getting the base64 string from IPFS
var stringval = filebuffer.toString();
console.log(stringval);
let encodedString = stringval.split(',')[1]; //getting the base64 hash
let mimetype = stringval.split(',')[0].split(':')[1].split(';')[0]; //getting the mime type
let data = atob(encodedString); //ascii to binary
var ab = new ArrayBuffer(data.length);
var ia = new Uint8Array(ab);
//converting to Uint8Array
for(var i = 0;i<data.length;i++){
ia[i] = data.charCodeAt(i);
}
let blob = new Blob([ia],{ "type": mimetype});
let filename = 'filename.' + App.getExtension(mimetype);
let file = new File([blob], filename);
link.href = window.URL.createObjectURL(file);
link.download = filename;
link.click();
}
I want to read xlsx file but what i want is just to read first three records because as you know if i read all the records, the browser will crash. I need your help to find a way to just read first three records (rows)
P.S: I don't want to save data in memory while parsing xlsx file
i am using this right now :
fileChange(event) {
const fileList: FileList = event.target.files;
if (fileList.length > 0) {
const file: File = fileList[0];
const reader = new FileReader();
reader.onload = e => {
const arrayBuffer = reader.result,
data = new Uint8Array(arrayBuffer),
arr = new Array();
for (let i = 0; i !== data.length; ++i) {
arr[i] = String.fromCharCode(data[i]);
}
const bstr = arr.join("");
const workbook: XLSX.WorkBook = XLSX.read(bstr, { type: "binary" });
const firstSheetName: string = workbook.SheetNames[0];
const worksheet: XLSX.WorkSheet = workbook.Sheets[firstSheetName];
this.setXlsxData(XLSX.utils.sheet_to_json(worksheet));
};
reader.readAsArrayBuffer(file);
}
}
setXlsxData(data: Array<any>) {
this.headers = Object.keys(data[0]);
this.xlsxData = data;
}
try this library. I have written & read some xlsx files, it works smoothly.
(Apologies, I couldnt write this in comment, can't comment)
https://www.npmjs.com/package/xlsx
I used a jquery plugin to crop images. The plugin will crop the image and give it to me as a base64 encoded string. In order to upload it to S3, I need to convert this into a file and pass the file into the upload function. How can I do this? I tried a lot of things including decoding the string using atob. None worked.
Here's the code of the cropping plugin ('croppie') which gives me the encoded string :
imageCropper.croppie('result', {
type: 'canvas',
size: 'viewport',
format: 'jpeg'
}).then(function (resp) {
updateAvatar(resp);
});
I pass it to a function called updateAvatar. Here's the updateAvatar function :
updateAvatar({Meteor, Slingshot}, avatar) {
const uploader = new Slingshot.Upload('userAvatarUpload');
uploader.send(avatar, function (error, downloadUrl) {
if (error) {
// Log service detailed response.
console.error('Error uploading', uploader.xhr.response);
console.log(error);
}
else {
console.log('uploaded', downloadUrl);
}
});
}
The uploader.send function expects a file or a url. It won't accept my encoded string.
The plugin which I use to upload files to S3 : https://github.com/CulturalMe/meteor-slingshot
It seems like the missing 'brick' in your code is a function that would take a base64-encoded image and convert it to a Blob.
So, I'm going to focus on that part exclusively with a short comment for each step.
The following function expects a string such as:
data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAMCAgICA...
function base64ImageToBlob(str) {
// extract content type and base64 payload from original string
var pos = str.indexOf(';base64,');
var type = str.substring(5, pos);
var b64 = str.substr(pos + 8);
// decode base64
var imageContent = atob(b64);
// create an ArrayBuffer and a view (as unsigned 8-bit)
var buffer = new ArrayBuffer(imageContent.length);
var view = new Uint8Array(buffer);
// fill the view, using the decoded base64
for(var n = 0; n < imageContent.length; n++) {
view[n] = imageContent.charCodeAt(n);
}
// convert ArrayBuffer to Blob
var blob = new Blob([buffer], { type: type });
return blob;
}
Convert the base64 string to blob, to be used in upload to S3. There are tidier ways of doing this of course! :)
Original SO Answer here: https://stackoverflow.com/a/16245768/1350913
imageCropper.croppie('result', {
type: 'canvas',
size: 'viewport',
format: 'jpeg'
}).then(function(resp) {
var contentType = 'image/png';
var s3Blob = b64toBlob(resp, contentType);
updateAvatar(s3Blob);
});
updateAvatar({
Meteor,
Slingshot
}, avatar) {
const uploader = new Slingshot.Upload('userAvatarUpload');
uploader.send(avatar, function(error, downloadUrl) {
if (error) {
// Log service detailed response.
console.error('Error uploading', uploader.xhr.response);
console.log(error);
} else {
console.log('uploaded', downloadUrl);
}
});
}
function b64toBlob(b64Data, contentType, sliceSize) {
contentType = contentType || '';
sliceSize = sliceSize || 512;
var b64DataString = b64Data.substr(b64Data.indexOf(',') + 1);
var byteCharacters = atob(b64DataString);
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;
}
The base64ToFile function (.ts) converts the base64 string into a File. The codeUnits and charCodes part make sure you can read Unicode text as ASCII by converting the string such that each 16-bit unit occupies only one byte.
Finally the download function (.ts) downloads the converted file from your browser to your local machine.
function base64ToFile(base64data: string, myFileNameWithdotExtention: string,
fileType: string): File {
let content = decodeURIComponent(escape(window.atob(base64data)));
let fileName = myFileNameWithdotExtention;
const codeUnits = Uint16Array.from(
{ length: content.length },
( _, index) => content.charCodeAt(index)
);
const charCodes = new Uint8Array(codeUnits.buffer);
const type = fileType; // 'text/csv' for instance
const blob = new Blob([charCodes], { type });
return new File([blob], fileName, { lastModified: new Date().getTime(), type });
}
download(){
let res: string = getMyDataFromSomewhere(); // base64 string
let data = base64ToFile(res);
let element = document.createElement('a');
window.URL = window.URL || window.webkitURL;
element.setAttribute('href', window.URL.createObjectURL(data));
element.setAttribute('download', data.name);
element.style.display = 'none';
document.body.appendChild(element);
element.click();
document.body.removeChild(element);
}
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>