I am sending a base64-encoded image as a string to my backend using node.js/express. I would like to store it in my Postgres database, but I can not fetch the string. Is there any limit to this?
Before reaching my AJAX call in frontend I fill the data with:
var data = {picture: ""};
const reader = new FileReader();
const get_picture = new Promise((resolve, reject) => {
//event handler
reader.onload = resolve;
reader.onerror = reject;
//read image
reader.readAsDataURL(file);
})
.then(() => {
data.picture = reader.result;
})
.catch(() => {
show_modal(modal.title.error_custom, modal.body.error_image);
});
console.log(target_data);
$.ajax({ [...]
And my console show as expected:
Object { picture: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFIA…"}
This is by express route:
router.post("/upload_image", (req, res, next) => {
const picture = req.body.picture;
console.log("test");
console.log(picture);
}
This shows an empty line in my backend console. Are there any limits to the size of the parameter? Or what am I doing wrong? Thanks
EDIT: this works with async/wait
$("#form").submit(async function (event) {
[...]
var data = {picture: ""};
const get_picture = await new Promise((resolve, reject) => {
//event handler
reader.onload = resolve;
reader.onerror = reject;
//read image
reader.readAsDataURL(file);
})
.then(() => {
data.picture = reader.result;
})
.catch(() => {
show_modal(modal.title.error_custom, modal.body.error_image);
});
$.ajax({ [...]
Your ajax call doesn't wait for the reading process of your file, and send the top initialized object (var data = {picture: ""}).
You should call your ajax request in the .then()
var data = {picture: ""};
const reader = new FileReader();
const get_picture = new Promise((resolve, reject) => {
//event handler
reader.onload = resolve;
reader.onerror = reject;
//read image
reader.readAsDataURL(file);
})
.then(() => {
data.picture = reader.result;
$.ajax({[...]});
})
.catch(() => {
show_modal(modal.title.error_custom, modal.body.error_image);
});
Related
I want a function which prompts the user to select an image. It should then wait for an image to be selected and then return that image. I want to achieve this without creating a new input element and attaching a new eventlistener every time (atleast not without removing the old ones first) because I expect this button to be used A LOT!
What I have right now is successfully prompting the user can getting the image. But I am not returning it so I can use it however I want after the prompt_for_image() function call. Please help me D:
I added a console log button for testing purposes so you can see the image is being selected propperly.
const images = [];
const file_input = document.createElement('input');
file_input.type = 'file';
file_input.accept = 'image/*';
file_input.addEventListener('change', () => {
const reader = new FileReader();
reader.onload = () => images.push(reader.result);
reader.readAsDataURL(file_input.files[0]);
});
function prompt_for_image() {
file_input.value = null;
file_input.click();
}
document.getElementById('btn_add_new_image').addEventListener('click', async () => {
await prompt_for_image();
});
document.getElementById('btn_log_images').addEventListener('click', () => { console.log(images) });
<button type='button' id='btn_add_new_image'>ADD NEW IMAGE</button>
<button type='button' id='btn_log_images'>console log image array</button>
You'll need to properly promisify FileReader, then promisify the addEventListener. This is easiest done by using the once parameter:
function readFileAsDataURL(file) {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = () => resolve(reader.result);
reader.onerror = reject;
reader.readAsDataURL(file);
});
}
function waitForNextEvent(element, type) {
return new Promise(resolve => {
element.addEventListener(type, resolve, {once: true});
});
}
Now you can do
const images = [];
const fileInput = Object.assign(document.createElement('input'), {
type: 'file',
accept: 'image/*',
});
async function promptForImage() {
const promise = waitForNextEvent(fileInput, 'change');
fileInput.value = null;
fileInput.click();
await promise;
return fileInput.files[0];
}
document.getElementById('btn_add_new_image').addEventListener('click', async () => {
images.push(await readFileAsDataURL(await promptForImage()));
//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
});
document.getElementById('btn_log_images').addEventListener('click', () => {
console.log(images);
});
function readFileAsDataURL(file) {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = () => resolve(reader.result);
reader.onerror = reject;
reader.readAsDataURL(file);
});
}
function waitForNextEvent(element, type) {
return new Promise(resolve => {
element.addEventListener(type, resolve, {once: true});
});
}
<button type='button' id='btn_add_new_image'>ADD NEW IMAGE</button>
<button type='button' id='btn_log_images'>console log image array</button>
I'm attempting to pass a file from an file input field's file list through FileReader and get the Base64 string to pass to the server via axios. The FileReader's onload function seems to get the string, but it evidently loses the string before it is returned. So, the value is undefined when I try to append it to the form data.
I'm told this is an asynchronous function, but I'm not sure where to await the promise. Can someone tell me what I'm doing wrong here?
const handleSubmit = async (e) => {
e.preventDefault()
const formData = new FormData()
// FILE READER -- DOES NOT WORK
const getImageFile = () => {
return new Promise(resolve => {
const reader = new FileReader()
reader.onload = function () {
const imageFile = reader.result
// console.log(`IMAGE FILE:\n ${imageFile}`) // imageFile IS NOT UNDEFINED HERE, BASE64 STRING
}
reader.readAsDataURL(document.getElementById("image").files[0])
})
}
////////////////////////////////
const imageFile = await getImageFile()
Array.from(document.getElementById("form").elements).forEach(element => {
switch (element.name){
case "image":
formData.append(`${element.name}`, imageFile) // UNDEFINED. WHY?
break
case "submit":
break
default:
formData.append(`${element.name}`, element.value)
}
})
console.log([...formData])
try {
const response = axios.post('http://localhost:4000/uploadShow', formData)
console.log(response)
} catch (e) {
console.log(e)
}
}
You have to create the promise yourself
const getImageFile = () => {
return new Promise(resolve => {
const reader = new FileReader()
reader.onload = function () {
resolve(reader.result)
}
reader.readAsDataURL(document.getElementById("image").files[0])
})
}
const handleSubmit = async (e) => {
// ...
const imageFile = await getImageFile()
// ...
I tried to create an image object by uploading an image file of 170MB Chrome Browser.
However, the error as below is occurring.
enter image description here
What's the cause?
Is there a size constraint on creating an image object?
const loadFromFile = (file: File) => {
return new Promise((resolve, reject) => {
const reader = new CustomFileReader()
reader.onload = () => resolve(reader.result)
reader.onerror = (e) => reject(e)
reader.readAsDataURL(file)
})
}
const createImage = (dataUrl) => {
return new Promise((resolve, reject) => {
const img = new Image()
img.onload = () => resolve(img)
img.onerror = (error) => { // generate Error Event
console.log('image load error', e)
reject(e)
}
img.src = dataUrl
})
}
const load = async (file: File) => {
const dataUrl = await loadFromFile(file) // successful
const image = await createImage(dataUrl) // error
}
This is the image used for the test: https://upload.wikimedia.org/wikipedia/commons/thumb/6/68/La_crucifixi%C3%B3n%2C_by_Juan_de_Flandes%2C_from_Prado_in_Google_Earth.jpg/2560px-La_crucifixi%C3%B3n%2C_by_Juan_de_Flandes%2C_from_Prado_in_Google_Earth.jpg
I made an API call to an endpoint and it returns this:
const test = () => {
fetch(endpoint)
.then((response) => {
console.log(response.body)
})
.catch((err) => {
console.log(err);
});
};
How can I obtain the ReadableStream in a Base64 format? This is returning a png file.
Using this answer, you can get the blob and convert it to base64.
const test = () => {
fetch(endpoint)
.then((response) => {
return response.blob();
})
.then((blob)=>{
var reader = new FileReader();
reader.readAsDataURL(blob);
reader.onloadend = function() {
var base64data = reader.result;
console.log(base64data);
}
})
.catch((err) => {
console.log(err);
});
};
MDN on .blob()
I am using react-native-facebook-login in order to get user data. Its returning me the url of the profile picture. when I paste this url in the browser the picture gets downloaded.
Its returning the following string named profile
{"id":"10210xxx114564932","name":"Stan Shivam","email":"ansh1602#gmail.com","first_name":"Shivam","last_name":"Stan","age_range":{"min":21},"link":"https:\/\/www.facebook.com\/app_scoped_user_id\/10210663114564932\/","picture":{"data":{"height":50,"is_silhouette":false,"url":"https:\/\/lookaside.facebook.com\/platform\/profilepic\/?asid=10210663114564932&height=50&width=50&ext=1523007905&hash=AeQ-_PZnt1JTbnth","width":50}},"gender":"male","locale":"en_GB","timezone":5.5,"updated_time":"2018-03-27T18:37:33+0000","verified":true}
What I want to do is I want to convert the url to base64 and send it to server. But I am not being able to find some good tut on this.
What I tried so far.
getBase64ImageFromUrl = async (imageUrl) => {
const res = await fetch(imageUrl);
console.log(res);
const blob = await res.blob();
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.addEventListener('load', () => {
resolve(reader.result);
}, false);
reader.onerror = () => {
return reject(this);
};
reader.readAsDataURL(blob);
});
};
calling it from constructor
this.getBase64ImageFromUrl('https://lookaside.facebook.com/platform/profilepic/?asid=10210663114564932&height=50&width=50&ext=1523007763&hash=AeSavHT5oXVEMq4w')
.then(result => console.log(result))
.catch(err => console.error(err));
But it gives me res.blob() is not a function.
What exactly do I need to use in order to achive it.
I resolved this using FileReader. use the following function and pass the url and callback. Thanks
export const toDataUrl = (url, callback) => {
const xhr = new XMLHttpRequest();
xhr.onload = () => {
const reader = new FileReader();
reader.onloadend = () => {
callback(reader.result);
};
reader.readAsDataURL(xhr.response);
};
xhr.open('GET', url);
xhr.responseType = 'blob';
xhr.send();
};
calling the function
toDataUrl('https://lookaside.facebook.com/platform/profilepic/?asid=10210663114564932&height=50&width=50&ext=1523007763&hash=AeSavHT5oXVEMq4w', (myBase64) => {
console.log(myBase64); // myBase64 is the base64 string
});