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));
}
};
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);
}
});
}
Here is code which i'm using to resize and compress images in javascript this working correctly and also send one image by ajax in mysql but issue is i want to send four images in database also some extra fields. Now i want imgCompressResize function just pass image parameter and return compress and resized image so i can save as i need.
<input type="file" name="img1" id="file1" accept="image/*">
document.getElementById("file1").addEventListener("change", function (e) {
var file = imgCompressResize(e);
var data = new FormData();
data.append('file1', file);
$.ajax({
url:"page.php",
type:"POST",
data:data,
cache: false,
contentType: false,
processData: false,
success:function (data) {
alert(data);
}
});
});
function imgCompressResize(e) {
const width = 500;
const height = 600;
var file;
const fileName = e.target.files[0].name;
console.log(fileName);
const reader = new FileReader();
reader.readAsDataURL(e.target.files[0]);
reader.onload = event => {
const img = new Image();
img.src = event.target.result;
img.onload = () => {
const elem = document.createElement('canvas');
elem.width = width;
elem.height = height;
const ctx = elem.getContext('2d');
ctx.drawImage(img, 0, 0, width, height);
ctx.canvas.toBlob((blob) => {
file = new File([blob], fileName, {
type: 'image/jpeg',
lastModified: Date.now()
});
return file;
// if i call here ajax() function that working for one image but i don't need
// call here ajax().
}, 'image/jpeg', .7);
},
reader.onerror = error => console.log(error);
}
}
I'm not going to rewrite this whole thing but simply give you an overview of using promises since onload is asynchronous.
document.getElementById("file1").addEventListener("change", function(e) {
const filesArray = Array.from(this.files);
// map array of each resize promise
const filePromises = filesArray.map(imgCompressResize);
var data = new FormData();
// when all resolved append to FormData
Promise.all(filePromises).then(newFiles =>{
newFiles.forEach(f=> data.append('files[]', f)
});
// append other fields needed
//then do ajax
})
function imgCompressResize(file) {
// ^^ file instead of event
// return promise
return new Promise((resolve, reject) => {
//...
//const fileName = e.target.files[0].name;
const fileName = file.name;
const reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = event => {
//...
img.onload = () => {
//....
const newFile = new File([blob], fileName, {...);
// resolve the promise
resolve(newFile);
});
});
});
reader.onerror = reject
}
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);
}
var image is not defined in alert :( please help , thank you so much!
handleBeforeUpload (file, event) {
var reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = (function () {
var f = reader.result;
});
var image = f;
alert(image)
var photo = {uri: image}
Your f variable is in scope of onload function callback. Define it outside of that function, where you define your reader variable, so it will be available in scope of handleBeforeUpload function
handleBeforeUpload (file, event) {
var reader = new FileReader();
var photo = null;
reader.readAsDataURL(file);
reader.onload = (function () {
f = reader.result;
photo = { uri: f }
});
}
How can I use Node FileSystem to open a file but have it sent to and read by the FileReader API?
const myFile = "C:\\Users\\Me\\Image.png";
fs.readFile(myFile, (error, data) => {
const blob = new Blob(data);
const fileReader = new FileReader();
fileReader.readAsDataURL(blob);
fileReader.addEventListener("load", () => {
const image = new Image();
image.src = fileReader.result;
document.body.appendChild(image);
});
});
This code doesn't throw an errors, but it doesn't work.
Thanks to the participants in the discussion above, the following code is a working solution. I've purposefully left out error handling for brevity.
const nodeFileSystem = require("fs");
const filePath = "C:\\path\\to\\image\\file.png";
nodeFileSystem.readFile(filePath, (error, data) => {
const blob = new Blob([data]);
const fileReader = new FileReader();
fileReader.readAsDataURL(blob);
fileReader.addEventListener("load", fileReaderLoadHandler);
});
function fileReaderLoadHandler(event) {
const fileReader = event.target;
fileReader.removeEventListener("load", fileReaderLoadHandler);
const image = new Image();
image.src = fileReader.result;
image.addEventListener("load", imageLoadHandler);
}
function imageLoadHandler(event) {
const image = event.target;
image.removeEventListener("load", imageLoadHandler);
document.body.appendChild(image);
}