I am attempting to convert an array of localhost URLs to base64 strings.
let uploadedBase64Images = [];
for (let i = 0; i < urls.length; i++) {
let img = await fetch(urls[i]);
let imgBlob = await img.blob();
let reader = new FileReader();
let base64;
reader.readAsDataURL(imgBlob);
reader.onloadend = () => {
console.log(reader.result)
base64 = reader.result;
console.log(base64)
uploadedBase64Images.push(base64)
};
}
console.log(uploadedBase64Images)
One thing I noticed is that the console.log(uploadedBase64Images) always prints before console.log(base64). This code block is wrapped in an async function as well. I've tried many other ways but at the end of the day, uploadedBase64Images is always empty.
When I move uploadedBase64Images.push(base64) outside of reader.onloadend, i.e.:
reader.onloadend = () => {
console.log(reader.result)
base64 = reader.result;
console.log(base64)
};
uploadedBase64Images.push(base64)
uploadedBase64Images is [undefined], which leads me to believe that the Promise isn't being resolved?
I appreciate any help on this, thanks in advance!
From what i see, the problem is the reader.onloadend, it is in its own zone which is not following the async behaviour.
So, by wrapping the reader function to Promise to wait for its response before doing anything may solve your problem
// wrapping reader in Promise
const convertImageToBase64 = async(imgBlob) => {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.readAsDataURL(imgBlob);
reader.onloadend = () => {
resolve(reader.result);
};
reader.onerror = reject
})
}
const uploadedBase64Images = [];
for (let i = 0; i < urls.length; i++) {
const img = await fetch(urls[i]);
const imgBlob = await img.blob();
const base64 = await convertImageToBase64(imgBlob)
uploadedBase64Images.push(base64)
}
console.log(uploadedBase64Images)
Related
I am using below 2 methods but I am unable to get back base64 string from it.
function convertFileToBase64(file) {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = () => resolve(reader.result);
reader.onerror = reject;
});
}
function previewProductImages(files){
let preveiwImagesTemplate = [];
for(let i=0; i<files.length; i++ ){
const uploadedImageBase64 = convertFileToBase64(files[i]);
/// WANT BASE64 HERE So I can pass that to another method
}
}
Replacement or better approches are welcome.
You should first assign a handler to the onload property - and then call the readAsDataURL() method, not the opposite.
function readFile(file)
{
return new Promise((resolve) =>
{
if (file.size)
{
const reader = new FileReader();
reader.onload = (e) =>
{
resolve({
binary: file,
b64: e.target.result,
});
};
reader.readAsDataURL(file);
}
});
}
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 am using tensorflowjs to do some front-end image classification. I am trying to use tf.browser.fromPixels to convert an img element to a tensor. However, I am getting all zeros of shape [160, 160, 3]. I am using the FileReader api to read an image from the file system via the <input type="file"> element. Here's some of the code:
function getFiles(event) {
const files = event.target.files;
let tempStore = [];
for (let i = 0; i < files.length; ++i) {
tempStore.push(files[i]);
}
return tempStore;
}
const imageElement = document.getElementById("upload");
imageElement.addEventListener("change", event => {
const files = getFiles(event);
Promise.all(files.map(loadImg)).then(d => {
console.log("All done !!!", d);
});
});
const loadImg = imgFile => {
return new Promise((resolve, reject) => {
let reader = new FileReader();
let imgEl = document.createElement("img");
reader.onload = async e => {
imgEl.src = e.target.result;
imgEl.setAttribute("width", 160);
imgEl.setAttribute("height", 160);
document.body.append(imgEl);
const fromPixels = tf.browser.fromPixels(imgEl);
resolve(fromPixels);
};
reader.onerror = reject;
reader.readAsDataURL(imgFile);
});
};
The image gets appended to document body properly.
The imageElement is of the form:
<img src="data:image/jpeg;base64,....." width=160 height=160>
You are creating the tensor from the image when the img tag has not yet been loaded. Here is the way to go
imgEl.src = e.target.result;
imgEl.setAttribute("width", 160);
imgEl.setAttribute("height", 160);
document.body.append(imgEl);
im.onload = () => {
// create the tensor after the image has loaded
const fromPixels = tf.browser.fromPixels(imgEl);
resolve(fromPixels);
}
I was trying to convert a blob to base64, and I found my way around, but while waiting the result from the function displayBase64String the map function in submitOffre returns an empty string even though console.log prints some data.
I'll appreciate any solution
here is my code.
submitOffre = (saleData) => {
debugger ;
var result = base64Service.displayBase64String(saleData);
console.log("========", result);
const rs = result.map(value => value.file); // Doesn't work.
console.log(rs); // rs is empty
}
class Base64Service {
blobToBase64 = (blob, callback) => {
var reader = new FileReader();
var data = '';
reader.onload = function () {
var dataUrl = reader.result;
var base64 = dataUrl.split(',')[1];
callback(base64);
};
reader.readAsDataURL(blob);
}
displayBase64String(formProps) {
const result = [];
const outbut = Object.entries(formProps.imageToUpload).map(([key, value]) => {
this.blobToBase64(value, (data) => {
result.push({ "file": `data:${value.type};base64,${data}` })
})
});
return result;
};
}
export default new Base64Service();
Something like that might help:
I've modified your code a bit, just to show you the basic pattern.
If you're doing more than 1 image at a time, you will need to use Promise.all, to keep track of more than 1 promise at once.
submitOffre = async (saleData) => { // SEE THE async KEYWORD
debugger ;
var result = await blobToBase64(saleData); // SEE THE await KEYWORD
console.log("========", result);
const rs = result.map(value => value.file); // Doesn't work.
console.log(rs); // rs is empty
}
I'll treat as if you were converting only 1 image.
blobToBase64 = (blob, callback) => new Promise((resolve,reject) => {
var reader = new FileReader();
var data = '';
reader.onload = function () {
var dataUrl = reader.result;
var base64 = dataUrl.split(',')[1];
callback(base64);
resolve(base64); // NOTE THE resolve() FUNCTION TO RETURN SOME VALUE TO THE await
};
reader.readAsDataURL(blob);
});
I want to resize an image before uploading it to the server (with Firebase):
api.uploadPhoto = async (file = {}, field = {}) => {
const canvas = document.getElementById('canvas')
const img = document.createElement('img')
const reader = new FileReader()
let fileToUpload
reader.onload = function (e) {
img.src = e.target.result
pica.resize(img, canvas).then(result => {
fileToUpload = pica.toBlob(result, 'image/jpeg', 90))
})
}
reader.readAsDataURL(file)
// run the code below only when reader.onload has finished
return await imageUpload.toFirebase(fileToUpload, field)
}
The problem is that imageUpload.toFirebase is running before reader.onload. How to fix this?
move the upload in to the callback ...
api.uploadPhoto = async (file = {}, field = {}, callback) => {
const canvas = document.getElementById('canvas');
const img = document.createElement('img');
const reader = new FileReader();
let fileToUpload;
reader.onload = function (e) {
img.src = e.target.result;
pica.resize(img, canvas).then(result => {
fileToUpload = pica.toBlob(result, 'image/jpeg', 90));
});
reader.readAsDataURL(file);
callback(await imageUpload.toFirebase(fileToUpload, field));
}
};