issue while uploading multiples images to firebase storage - reactjs

I am trying to upload multiples images to firebase storage , using react native for an android project , once images got uploaded I should get back download urls .
I have tested 2 methods, first one , upload is fine , but as result I got only download urls of last item.
second method , no upload , neither download urls has succeded, could you please help and correct my code , here is my code :
my first method :
const [downloadUrls , setDownloadUrls] = useState([])
const [images , setImages] = useState([])
useEffect(()=>{
if(downloadUrls !== null) {
console.log(downloadUrls , 'urlx');
}else{
console.log('no downloadUrls')
}
},[images, selectedIndex,downloadUrls ]);
...
let filename;
let imageRef;
let promise1;
let promise2;
let task = storage();
if(images !== null){
images.map( async (item , index)=>{
// uri = item;
filename = item.substring(item.lastIndexOf('/') + 1);
imageRef = storage().ref(filename);
if(imageRef){
setUploading(true)
}
// uploading images
await imageRef.putFile(item).then(()=> {setUploading(false), setImageCounter((p) => p+1 )
} ).catch((error) => { console.log('error22') }) ;
// get back download urls
await imageRef.getDownloadURL().then((img) => setDownloadUrls((previouse) => [...previouse, img])).catch((error) => { console.log(error) });
})
//setImages([])
}
in my secod test , I've tried to work with promises but it failed , no upload , no download urls,
here is my code :
let filename;
let imageRef;
let promise1;
let promise2;
let task = storage();
if(images !== null){
images.map( async (item , index)=>{
filename = item.substring(item.lastIndexOf('/') + 1);
imageRef = storage().ref(filename);
if(imageRef){
setUploading(true)
}
promise1 = new Promise((resolve , reject) =>{
imageRef.putFile(item);
resolve(()=>{
setUploading(false);
});
reject((e) =>{
console.log(e)
})
});
promise2 = new Promise((resolve , reject) =>{
imageRef.getDownloadURL();
resolve((e)=>{
setDownloadUrls( (urls ) => [...urls , e])
})
reject((e) => console.log(e))
})
//setImages([])
Promise.all([promise1, promise2])
}
thank you for your help

Related

how can i delete multiples request at the same time using axios and an array of URL

im doing an app and the first code is working deleting a "task" in my API, but in my app each task have a checkbox input, so, i want to delete all the tasks that are checked.
i used this code to delete single task with a button.
const baseURLtasksId = `https://63cf2168e52f5878299ab5e2.mockapi.io/api/users/${userid}/tasks/${taskId}`
axios.delete(baseURLtasksId, { done: true }).then()
}
ArrayUrlById this is an array of all the URL's that are checked
const deleteAll = () => {
let ArrayUrlById = []
ArrayUrlById = isChecked.map((cId) => {
let arrayURL = `https://63cf2168e52f5878299ab5e2.mockapi.io/api/users/${userid}/tasks/${cId}`
return arrayURL
})
console.log(ArrayUrlById); // here i have an array of the URL
// i need to delete now multiples tasks, using an array of URL and sending {done:true} for each one
}
i tried with this code, but not working properly, beacuse never delete all of them, even in the console send all the delete request to the endpoint with a 200 status, but after i refresg the website, is not deleting all of them that are checked
const deleteAll = () => {
let ArrayUrlById = []
console.log('aqui');
ArrayUrlById = isChecked.map((c) => {
let arrayURL = `https://63cf2168e52f5878299ab5e2.mockapi.io/api/users/${userid}/tasks/${c}`
return arrayURL
})
console.log(ArrayUrlById);
const requests = ArrayUrlById.map(url => axios.delete(url));
axios.all(requests)
.then(responses => {
responses.forEach(response => console.log(response.data));
})
.catch(error => {
console.log(error);
})
}
enter image description here

getDownloadURL in array of dictionary (re-rendering issue, forEach)

I have an array of dictionaries, (e.g. [{}, {}, {}, {}], each dictionary contains information about book)
I want to download image from firebase storage using getDownloadURL.
My current code's like...
const [resObj, setresObj] = useState() // empty variable for update state
let result = [] //create empty array for copy & push new obj
useEffect(() => {
props.resObj.forEach((obj) => { // props.resObj: array of dictionary I explained before
const jpgName = 'bookDB/'+ obj.도서번호 + '.jpg';
const imgRef = ref(storage, jpgName)
getDownloadURL(imgRef)
.then((url) => {
result1.push({
...obj,
bookUrl: url
}) // copy & push dictionary
})
.catch((error) => {
if (error.code === 'storage/object-not-found') {
console.log('이미지 파일 없음')
result1.push({
...obj,
bookUrl: "https://upload.wikimedia.org/wikipedia/commons/a/ac/No_image_available.svg"
})
} else { console.log(error)}
})
})
setresObj(result1)
}, [])
after this code update 'resObj' variable,
I map resObj in component like...
return (
<div>
{resObj? resObj.map(item => {
<img
key = {}
className = '~~'
onClick = {}
src = {item.bookUrl}
/>
})}
</div>
)
unfortunately.. it doesn't show nothing..
It seems that forEach, useEffect, useState, getDownloadURL Promise seriously entangled..
I tried 1) devide download image code as function, 2) devide download image code as recoil, 3) escape download image code from useEffect, 4) ...(extra variances of code)...
The problem is that your call to setresObj happens before any of the calls to result1.push have happened, so you're always setting an empty array. It's easiest to verify this by setting breakpoints and running in the debugger, or by adding some console.log calls.
The fix is to use Promise.all to wait for all download URLs to have been retrieved and only then call setresObj. Something like this:
useEffect(() => {
let promises = props.resObj.map((obj) => {
const jpgName = 'bookDB/'+ obj.도서번호 + '.jpg';
const imgRef = ref(storage, jpgName)
return getDownloadURL(imgRef)
.then((url) => {
return {
...obj,
bookUrl: url
}
})
.catch((error) => {
if (error.code === 'storage/object-not-found') {
console.log('이미지 파일 없음')
result1.push({
...obj,
bookUrl: "https://upload.wikimedia.org/wikipedia/commons/a/ac/No_image_available.svg"
})
} else { console.log(error)}
})
})
Promise.all(promises).then((results) => {
setresObj(results);
});
}, [])

Imgly plugin is not exporting captured image

I have an Ionic app built with angular. I have integrated Imgly in my app. But it is not working properly. After editing an image the plugin is not exporting that image. I have looked into many documentation's but haven't found any solution on this.
Method capturing image and opening Imgly plugin
captureImage2() {
if (this.usepicker) {
this.filePickerRef.nativeElement;
// this.filePickerRef.nativeElement.click();
// return;
}
const options: CaptureImageOptions = { limit: 1 };
this.mediaCapture.captureImage(options).then(
async (data: MediaFile[]) => {
const fullPath = data[0].fullPath;
const directoryPath = fullPath.substring(0, fullPath.lastIndexOf("/"));
const fileName = fullPath.substring(fullPath.lastIndexOf("/") + 1);
console.log(
"File Details ======>>>>>>",
fullPath,
directoryPath,
fileName
);
PESDK.openEditor(
async (data1) => {
console.log("REEEEEE =====> ", JSON.stringify(data1));
await this.toProcessImage(data1.image);
const check = await this.displayImage(data1.image);
// console.log(check);
this.onButtonClick(data1.image);
// const dataURL = await this.file.readAsDataURL(data1.image, fileName);
// console.log("DATA URL ======>>>>>>" + dataURL);
data1
.save()
.then(async (sceneAsString) => {
const file = {
dataURI: sceneAsString,
directory: this.dic,
};
const fileResponse = await UriFileUpload(file);
if (fileResponse) {
console.log("image UPLOADED", JSON.stringify(fileResponse));
this.toastSer.success("uploaded");
// this.uploadedList = [...this.uploadedList , fileResponse1];
// console.log(this.uploadedList);
this.updateFiles.next(fileResponse);
} else {
this.toastSer.error("Somthing went wrong!");
}
})
.catch((error) => {
console.error("Save failed", error);
});
},
(error) => console.log(error),
fullPath
);
},
(err: CaptureError) => console.error(err)
);
}
IMG.LY team here!
We would like to provide a correct answer, but keep in mind that for this type of issue, a minimal example project is required in order to test what the different outputs are from the used camera and image picker plugin.
You can find Stack Overflow's suggestions here for a minimal project.
Feel free to submit your further queries to our Support Desk, we're always happy to help.

Lifecycle of useState hook in React.js

I have the following synchronism problem. Given that I know that the React useState hook is asynchronous, I run into the following: I'm downloading some images from Amazon S3, I manage to save it correctly in my hook: defaultSelfiePicture and depending on the weight of the image (or so I think) sometimes I get the images loaded correctly and sometimes not. I have tried to force state changes after I finish saving the object in my hook but it never renders the image, only if I change component and come back is when it is shown in the cases that it takes longer to load.
const [defaultSelfiePictures, setDefaultSelfiePictures] = useState([])
useEffect(() => {
if (savedUser.docs !== undefined) {
loadAllPictures()
}
}, [savedUser.docs.length])
const loadAllPictures = () => {
let p1 = loadUrlDefaultFrontPictures()
let p2 = loadUrlDefaultBackPictures()
let p3 = loadUrlDefaultSelfiePictures()
Promise.all([p1, p2, p3]).then(result => {
console.log('end all promises')
setTimestamp(Date.now())
})
}
const loadUrlDefaultSelfiePictures = async () => {
if (savedUser.docs.length > 0) {
let readedPictures = []
for (let i = 0; i < savedUser.docs.length; i++) {
if (
savedUser.docs[i].type === 'SELFIE'
//&& savedUser.docs[i].side === 'FRONT'
) {
if (
savedUser.docs[i].s3Href !== null &&
savedUser.docs[i].s3Href !== undefined
) {
const paramsKeyArray =
savedUser.docs[i].s3Href.split('')
let paramsKey = paramsKeyArray.pop()
let params = {
Bucket: process.env.REACT_APP_S3_BUCKET,
Key: paramsKey
}
await s3.getSignedUrl('getObject', params, function (err, url) {
readedPictures.push({
idKycDoc: savedUser.docs[i].idKycDoc,
name: 'selfie.jpeg',
type: savedUser.docs[i].type,
url: url
})
})
} else {
let urlPicture = savedUser.docs[i].localHref
let response = await axios.get(`${URL_IMG}${urlPicture}`, {
responseType: 'blob'
})
function readAsDataURL(data) {
return new Promise((resolve, reject) => {
const reader = new FileReader()
reader.readAsDataURL(data)
reader.onloadend = () => {
resolve(reader.result)
}
})
}
const base64Data = await readAsDataURL(response.data)
readedPictures.push({
idKycDoc: savedUser.docs[i].idKycDoc,
name: 'selfie.jpeg',
type: savedUser.docs[i].type,
url: `data:image/jpeg;base64,${base64Data.slice(21)}`
})
}
}
}
setDefaultSelfiePictures(readedPictures)
}
}
And I obtain this :
I can see that the hook has content, but that content is not updated until the next rendering of the component, also if I try to make any changes when I detect that the .length has changed it tells me that it is 0...
And right after the next render I get this:

Uploading images from react with laravel api

I'm having trouble uploading files from a react input using a laravel API.
I'm working with react-hook-form.
My form and onSave are as follows
const onSave = data => {
// data.picture = imgs; here I tried changing the picture to event.target.files from the file input, didn't work either.
axios.defaults.headers.common["Authorization"] = "Bearer " + token;
axios
.post(`/api/products/store`, data, {})
.then(res => {
console.log(res);
})
.catch(err => console.log(err));
};
return (
<form onSubmit={handleSubmit(onSave)} encType="multipart/form-data">
<input
type="file"
name="picture[]"
label="Product Picture"
onChange={handlePicInput}
className={classes.inputFile}
multiple
/>
//other inputs
</form>
);
my post request leads to this controller method
public function store(Request $request)
{
$imageNames = '';
$pictures = (object) $request->file('picture');
//$pictures = $request->allFiles();
//$pictures = (object) $request->file('picture[]');
//$pictures = (object) $request->files;
foreach ($pictures as $key => $picture) {
/*WHEN I'M USING POSTMAN OR INSOMNIA,
this foreach loop is accessed but
the react form just skips the foreach completely */
$imageNames = $imageNames . $picture->store('product_pictures', 'public') . ',';
}
$product = Product::create([
'name' => $request->name,
'prices_amountmax' => $request->prices_amountmax,
'prices_amountmin' => $request->prices_amountmax,
'brand' => $request->brand,
'manufacturer' => $request->manufacturer,
'weight' => $request->weight,
'category_id' => $request->category_id,
'stock' => $request->stock,
'imageurls' => $imageNames
]);
$product->save();
}
To sum up, I tested uploading images with postman, it works just fine, so the problem must be in the react form?
Thank you for any kind of help
To upload images using js you can use FormData. I can't see your handlePicInput method to understand how input change is handled, but may be this snippet can help you to understand what to do further.
function handlePicInput(event){
let images = event.target.files
let fd = new FormData()
fd.append("images", images);
}
Then you can append to fd your other values and send via axios
axios.post(`/api/products/store`, fd)
Again, where to place the code and how to handle other inputs you have to manage by yourself, or provide more data
Try sending it as formData, with multiple files:
const onSave = data => {
const formData = new FormData();
for (let i in data) {
if(i === 'picture[]'){
for(let file of data[i]){
formData.append('picture',file);
}
}else{
formData.append(i, data[i])
}
}
// data.picture = imgs; here I tried changing the picture to event.target.files from the file input, didn't work either.
axios.defaults.headers.common["Authorization"] = "Bearer " + token;
axios
.post(`/api/products/store`, formData, {})
.then(res => {
console.log(res);
})
.catch(err => console.log(err));
};
I tested it with my Node/Express backend and it seems to work. "picture" will be an array of files. If your php backend doesn't recognize this correctly, try changing the formData.append('picture',file) to formData.append('picture[]',file), but then you'll also need to change the name in your php.

Resources