I am using react-dropzone plugin for file uploads. I worried how i can convert each file to base64:
eg:
Here is my function where i get files:
I am creating here for example thumb for each file and attach to object. But how add to item here prop like base64string: and it will keep base64 data for each file?
this.onDrop = files => {
files.map(file =>
Object.assign(file, {
preview: URL.createObjectURL(file),
})
);
};
check this out,you can get files and then you can store them into images array of state instance.
onDropHandler = (files) => {
files.map(file => {
const reader = new FileReader();
reader.onload = (event) => {
//store result into your state array.
this.setState(prevState => {
const updatedImages = [...prevState.images, event.target.result];
return {
images: updatedImages,
}
})
console.log(event.target.result);
};
reader.readAsDataURL(file);
});
}
With this code you get an array with the base64 data and blob url for the preview.
const [data, setData] = useState([])
const onDrop = (files) => {
files.map((file) => {
const reader = new FileReader()
reader.onload = (e) => {
setdata(
files.map((file) =>
Object.assign(file, {
preview: URL.createObjectURL(file),
base64Image: e.target.result,
})
)
)
}
reader.readAsDataURL(file)
})
}
Related
I have a custom hook called useBase64 where I convert my image to Base64. This hook accepts an initial value and returns handleCreateBase64 function and logo (piece of state). handleCreateBase64 converts the file to base64 and stores it in logo. I am sending an array of images as File and then mapping through that array and I want to store it in logo and then send it to that component. right now the problem is that in the logo I can only see 1 base64 even if I select multiple files.
useBase64 hook: -
import { useCallback, useState } from "react";
export const useBase64 = (initialValue) => {
const [logo, setLogo] = useState(initialValue)
const handleCreateBase64 = useCallback(async (receivedFile) => {
let file = receivedFile;
if(initialValue instanceof Array) {
file = Object.values(receivedFile)
file.map(async el => {
const base64 = await convertToBase64(el)
setLogo([...logo, base64])
})
}
});
const convertToBase64 = (file) => {
return new Promise((resolve, reject) => {
const fileReader = new FileReader();
if (!file) {
console.log("no image");
} else {
fileReader.readAsDataURL(file);
fileReader.onload = () => {
resolve(fileReader.result);
};
}
fileReader.onerror = (error) => {
reject(error);
};
});
};
return { handleCreateBase64, logo }
}
The result: -
As you can see above that I have 3 images selected but I see only 1 base64. I am quiet new to this so it will be great if full explanation is provided.
Wrong use of map and setState
Try:
const items = await Promise.all(file.map(el => convertToBase64(el)))
setLogo([...logo, ...items])
I have an imported file: import ExportReportCardTemplate from "asset/files/excel/report_card_template.xls";
How can I use it with library import * as xlsx from "xlsx-js-style";
I've searching but all I get is reading xls file with input, how can I read a local file and then use it with xlsx?
After following tpliakas' answer, I got this error:
First you should read file as a binary string, so you have to do something like this
function readFile(file) {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = (e) => {
resolve(e.target.result);
};
reader.onerror = (e) => {
reject(e);
};
reader.readAsBinaryString(file);
});
}
Then you should parse this binary string to a workbook:
async function readExcel() {
// Wait for the binary string first
const binaryString = await readFile(ExportReportCardTemplate);
const wb = xlsx.read(binaryString, { type: 'binary' });
// use the wb here
}
After following tpliakas answer, I had a bit adjustment and finally I can read the local file to workbook data, here is the code:
import ExportReportCardTemplate from "asset/files/excel/report_card_template.xls";
import * as xlsx from "xlsx-js-style";
const readFile = (file) => {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = (e) => {
resolve(e.target.result);
};
reader.onerror = (e) => {
reject(e);
};
fetch(file)
.then((response) => response.blob())
.then((file) => reader.readAsBinaryString(file));
});
};
export const exportReportCardExcel = async (data) => {
try {
const binaryString = await readFile(ExportReportCardTemplate);
const workbook = xlsx.read(binaryString, { type: "binary" });
console.log("workbook:::", workbook);
} catch (error) {
console.log("error:::", error);
}
};
Is there a way to delete all uploaded files at once? When I uploaded success. I want to call event remove all files. I didn't find any solution for this. Tks for all the help !
Here is my code:
upload file
const [fileDatas, setFileDatas] = useState([]);
const dummyRequest = ({ file, onSuccess }) => {};
const beforeUpload = (file, fileList) => {return false};
const { Dragger } = Upload;
const props = {
accept: 'image/png, image/jpeg, image/svg, image/gif, .xlsx,.xls,image/*,.doc, .docx,.ppt, .pptx,.txt,.pdf',
name: 'file',
multiple: true,
beforeUpload: beforeUpload,
action: dummyRequest,
onChange({ file, fileList }) {
if (file.status !== 'uploading') {
setFileUploads(fileList);
}
},
onDrop(e) {
console.log('Dropped files', e.dataTransfer.files);
setFileUploads(e.dataTransfer.files);
},
};
handle event submit upload file
const handleUploadFile = () => {
if (fileUploads.length === 0) {
toastActionWarning('No files to upload');
}else{
setFileUploads([]);
const formDatas = new FormData();
fileUploads.forEach((file) => {
formDatas.append(file.name, file.originFileObj);
});
axios
.post('files', formDatas, { withCredentials: true })
.then((res) => {
let newList = [...fileDatas];
res.data.data.forEach(element => {
element.author = window.userDisplayName;
newList = [element, ...newList]
});
setFileDatas(newList);
//I want to clear all file here
toastActionSuccess('Upload successfully');
})
.catch((error) => {
toastActionFailed('There was an error in processing');
});
}
};
const sendImageToFirebase = (e) => {
const promises = []
const urlsArray = []
// productimage is an array of image files
productImage.forEach((image, i) => {
var storageRef = firebase.storage().ref();
var uploadTask = storageRef.child(`${userDetailsFirebase.uid}/` + Math.random()).put(image);
promises.push(uploadTask.on('state_changed',
(snapshot) => {
},
(error) => {
console.log("error");
},
async () => {
const downloadurl = await uploadTask.snapshot.ref.getDownloadURL()
urlsArray.push(downloadurl)
}
))
})
Promise.all(promises).then(res => {
db.collection("products").doc(idGeneratedforProduct).set(
{
imageURL: urlsArray, //array of image urls
},
).then(e => {
}).catch(error => console.log("Error while sendig items to Firebase"))
})
}
I want to upload a multiple images to firebase storage. Here, sendImagToFirebase is a normal function in reactJs, and productimage is an array of image files. I want to wait for URL for each image files and then store all of them as an array to firestore. I would appreciate your input on how to do it?
You can create a function that receoves the ref and the file and returns the downloadURL. By calling it for each file with a Promise.all you get as result your array of downloadURLs:
const uploadFileAndGetDownloadURL = async (ref, file) => {
const snap = await ref.put(file);
const downloadURL = await snap.ref.getDownloadURL();
return downloadURL;
};
const sendImageToFirebase = async (e) => {
const promises = [];
productImage.forEach((image, i) => {
var storageRef = firebase.storage().ref();
var ref = storageRef.child(`${userDetailsFirebase.uid}/` + Math.random());
promises.push(uploadFileAndGetDownloadURL(ref, image));
});
//Your array with the urls
const urlsArray = await Promise.all(promises);
};
I am in React hooks trying to utilise code in this question Stackoverflow question- but, as I think someone is pointing out, there are problems implementing this in a local environment.
I have a variable containing my src path:
import avatar from '../../Assets/Photos/avatar.png'
Then I try to set the photo as a useState state:
const [ photo, setPhoto ] = useState(avatar)
Then I use useEffect to wait until the variable has loaded:
useEffect(() => {
if (photo) {
console.log("PHOTO EXISTS!!!!!!!!!!!!!!", photo)
console.log(convertImgToBase64())
}
}, [photo])
And the convertImgToBase64 function is almost identical to the one in the question I referenced:
function convertImgToBase64()
{
var canvas = document.createElement('CANVAS');
let img = document.createElement('avatar');
img.src = photo;
img.onload = function()
{
canvas.height = img.height;
canvas.width = img.width;
var dataURL = canvas.toDataURL('image/png');
canvas = null;
return dataURL
};
}
This returns undefined - why is this please?
Create an image state:
const[image, setImage] = useState("")
Function to convert to base64:
const convertBase64 = (file) => {
return new Promise((resolve, reject) => {
const fileReader = new FileReader();
fileReader.readAsDataURL(file);
fileReader.onload = () => {
resolve(fileReader.result);
};
fileReader.onerror = (error) => {
reject(error);
};
});
};
Set your image state to base64 string image:
const handleFileRead = async (event) => {
const file = event.target.files[0];
const base64 = await convertBase64(file);
setImage(base64);
};
<input type="file" multiple accept="image/gif, image/jpeg, image/png" onChange={(e) => handleFileRead(e)} />