Base64 to String in javascript - javascript

I have this code that transforms an image url to base64, it works perfectly but I haven't found a way to convert the result to a string, I need to convert it to a string since I have to POST via an API, any idea I'm doing wrong? :(
const toDataURL = url => fetch(url)
.then(response => response.blob())
.then(blob => new Promise((resolve, reject) => {
const reader = new FileReader()
reader.onloadend = () => resolve(reader.result)
reader.onerror = reject
reader.readAsDataURL(blob)
}))
toDataURL('https://www.gravatar.com/avatar/d50c83cc0c6523b4d3f6085295c953e0')
.then(dataUrl => {
console.log('RESULT:', dataUrl)
})
most likely it's something super simple that I'm failing :(

"what I need is to pass the result that the console.log gives me to show it on the screen as a string"
then just do that
const toDataURL = url => fetch(url)
.then(response => response.blob())
.then(blob => new Promise((resolve, reject) => {
const reader = new FileReader()
reader.onloadend = () => resolve(reader.result)
reader.onerror = reject
reader.readAsDataURL(blob)
}))
toDataURL('https://www.gravatar.com/avatar/d50c83cc0c6523b4d3f6085295c953e0')
.then(dataUrl => {
document.getElementById("blob-string").innerText = dataUrl;
})
<p id="blob-string"></p>

Related

File uploader crashing for files larger than 300kb when using readAsDataURL on FileReader object

I am currently using the following method to convert files to base64 which crashes the browser(chrome) or abandons the job(firefox) when uploading larger files:
export const convertFilesToBase64: (
files: File[]
) => Promise<Base64FileObject[]> = async (files: File[]) => {
const toBase64 = async (file: File) =>
await new Promise((resolve, reject) => {
const reader = new FileReader()
reader.readAsDataURL(file)
reader.onload = () => resolve(reader.result)
reader.onerror = (error) => reject(error)
})
if (files.length > 0) {
return await Promise.all(
files.map(async (file: File) => {
const database64 = (await toBase64(file)) as string
return {
filename: file.name,
url: URL.createObjectURL(file),
size: file.size,
dataBase64: database64.replace(/^data:.*\/.*,/, ''),
}
})
)
} else {
return []
}
}
Smaller files seem to work without any issues. It currently seems to fail on the reader.readAsDataURL(file) line. Not sure if I am missing something obvious here?

Convert fetch to axios

I did a 'get' with fetch but I want to do it with axios, could someone help me convert this code to axios?
detail: detail: I made the request to get an image, and I use the blob to be able to show this image to the user, and I would like to do that with axios as well.
Code:
const image = (url) =>
fetch(url)
.then((response) => {
return response.blob();
})
.then(
(blob) =>
new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onloadend = () => resolve(reader.result);
reader.onerror = reject;
reader.readAsDataURL(blob);
})
);
const image = async (url) =>
await axios.get(url)
.then(response => {
// can access blog directly from response...
}
Read more about axios here
Here: I am assuming this is a get request?
const image = async (url) => {
return await axios.get(url)
.then((response) => {
return response.blob();
})
.then(
(blob) =>
new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onloadend = () => resolve(reader.result);
reader.onerror = reject;
reader.readAsDataURL(blob);
})
);
}

How to convert local pdf to base64?

I have a local pdf file that I want to receive and convert to base64
import file from 'assets/PDFs/file.pdf';
const getBase64 = async (file) => new Promise((resolve, reject) => {
const reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = () => resolve(reader.result);
reader.onerror = error => reject(error);
});
const fileURI = new File([file], 'file')
const base64Pdf = await getBase64(fileURI);
Finnaly, instead of a base64 file, I got a text file which contain a path to file assets/PDFs/file.pdf
For node environment:
import fs from 'fs'
try {
const data = fs.readFileSync('assets/PDFs/file.pdf', 'utf8')
const buff = new Buffer.from(data)
const base64pdf = 'data:application/pdf;base64,' + buff.toString('base64')
console.log(base64pdf)
} catch (err) {
console.error(err)
}
For browser environment:
const getBase64 = async(file) => new Promise((resolve, reject) => {
const reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = () => resolve(reader.result);
reader.onerror = error => reject(error);
});
const file = document.querySelector("input").onchange = async(e) => {
let b64Data = await getBase64(e.target.files[0]);
console.log(b64Data)
}
<input type="file" accept=".pdf" />

How to return base64 data from a fetch promise?

I want to convert images from a URL to base 64, and store that in a state for later use.
How do I return the data from fetch()?
I can get it to work using CORS safe images and an HTML canvas, but this will not work for public domains.
openImage = (index) => {
const url = formatURLs[index];
const base64 = this.getBase64Image(url);
this.setState(prevState => ({
currentImage: index,
currentImagebase64: base64
}));
}
getBase64Image(url) {
fetch(url).then(r => r.blob()).then(blob => {
var reader = new FileReader();
reader.onload = function() {
var b64 = reader.result.replace(/^data:.+;base64,/, '');
return b64;
};
reader.readAsDataURL(blob);
});
}
When I console.log(reader.result), it will output base64 as expected.
However when I return b64, it returns to openImage as 'undefined'.
getBase64Image is async so when calling it in a sync way it will return undefined.
You can try something like that
openImage = async (index) => {
const url = formatURLs[index];
const base64 = await this.getBase64Image(url);
this.setState(prevState => ({
currentImage: index,
currentImagebase64: base64
}));
}
async getBase64Image(url) => {
const response = await fetch(url);
const blob = await response.blob();
const reader = new FileReader();
await new Promise((resolve, reject) => {
reader.onload = resolve;
reader.onerror = reject;
reader.readAsDataURL(blob);
});
return reader.result.replace(/^data:.+;base64,/, '')
}
You have to set state inside .then()
getBase64Image(url) {
fetch(url).then(r => r.blob()).then(blob => {
var reader = new FileReader();
reader.onload = function() {
var b64 = reader.result.replace(/^data:.+;base64,/, '');
this.setState({
currentImagebase64: b64
});
};
reader.readAsDataURL(blob);
});
}

promise with FileReader does not give desired deferred result

After using an file input element I would like upload selected files subsequently. Reading the files with FileReader is asynchronous so I tried to defer the upload function call with a promise. It does not work however as the vm.upload() gets called when vm.files array is 'not yet filled'. There is no error from the promise by the way.
Why does the promise not 'wait/ defer'? It might be since I should make a promise closer to the async code (in the map method), but I am not sure why?
let filesPromise = inputFiles => {
return new Promise((resolve, reject) => {
inputFiles.filter(file => !this.queue.some(f => file.name === f.name))
.map(file => {
file.__size = humanStorageSize(file.size)
if (this.noThumbnails || !file.type.startsWith('image')) {
this.queue.push(file)
}
else {
const reader = new FileReader()
reader.onload = (e) => {
let img = new Image()
img.src = e.target.result
file.__img = img
this.queue.push(file)
this.__computeTotalSize()
}
reader.readAsDataURL(file)
}
return file
})
resolve(inputFiles)
reject(new Error('An error occurred in filesPromise'))
})
}
filesPromise(eventFiles)
.then(eventFiles => vm.files.concat(eventFiles))
.then(() => vm.upload())
.catch(error => console.log('An error occurred: ', error))
As #baao commented, a map method containing async code (FileReader event) will just continue and not wait. To solve this the FileReader needs to be put into a Promise and to keep using map with Promises one should build an array consisting of Promise-elements. On this array you can subsequently run Promise.all. This code works:
let filesReady = [] // List of image load promises
files = inputFiles.filter(file => !this.queue.some(f => file.name === f.name))
.map(file => {
initFile(file)
file.__size = humanStorageSize(file.size)
file.__timestamp = new Date().getTime()
if (this.noThumbnails || !file.type.startsWith('image')) {
this.queue.push(file)
}
else {
const reader = new FileReader()
let p = new Promise((resolve, reject) => {
reader.onload = (e) => {
let img = new Image()
img.src = e.target.result
file.__img = img
this.queue.push(file)
this.__computeTotalSize()
resolve(true)
}
reader.onerror = (e) => {
reject(e)
}
})
reader.readAsDataURL(file)
filesReady.push(p)
}
return file
})
if (files.length > 0) {
vm.files = vm.files.concat(files)
Promise.all(filesReady)
.then(() => vm.upload())
.catch(error => console.log('An error occurred: ', error))
}

Categories