Based on the example given in the documentation of expo image picker I'm trying to upload multiple images to AWS Amplify. In the example given on github only one picture is being worked with. Setting the allowsMultipleSelection prop to true makes it possible to pick multiple images but though I've been tinkering with the code to suit it to my need I can't seem to get it.
Here's what I'm doing
import { Amplify, Auth, Storage } from "aws-amplify";
import * as Clipboard from "expo-clipboard";
import * as ImagePicker from "expo-image-picker";
import { useState } from "react";
import { Button, Image, Text, View } from "react-native";
import awsconfig from "../aws-exports";
Amplify.configure(awsconfig);
const UploadImageAWS = () => {
const [image, setImage] = useState([]);
const [percentage, setPercentage] = useState(0);
const pickImage = async () => {
let result = await ImagePicker.launchImageLibraryAsync({
mediaTypes: "Images",
aspect: [4, 3],
quality: 1,
allowsMultipleSelection: true,
});
this.handleImagePicked(result);
};
handleImagePicked = async (pickerResult) => {
try {
if (!pickerResult.canceled) {
pickerResult.forEach(async (element) => {
setPercentage(0);
const img = await fetchImageFromUri(element.uri);
const uploadUrl = await uploadImage(img.name, img);
downloadImage(uploadUrl);
});
}
} catch (e) {
alert("Upload failed");
}
};
uploadImage = (filename, img) => {
Auth.currentCredentials();
return Storage.put(filename, img, {
level: "public",
contentType: "image/jpeg",
progressCallback(progress) {
setLoading(progress);
},
})
.then((response) => {
return response.key;
})
.catch((error) => {
return error.response;
});
};
const setLoading = (progress) => {
const calculated = parseInt((progress.loaded / progress.total) * 100);
updatePercentage(calculated); // due to s3 put function scoped
};
const updatePercentage = (number) => {
setPercentage(number);
};
downloadImage = (uri) => {
Storage.get(uri)
.then((result) => setImage(result))
.catch((err) => console.log(err));
};
const fetchImageFromUri = async (uri) => {
const response = await fetch(uri);
const blob = await response.blob();
return blob;
};
const copyToClipboard = () => {
Clipboard.setString(image);
alert("Copied image URL to clipboard");
};
return (
<View style={styles.container}>
<Text style={styles.title}>AWS Storage Upload Demo</Text>
{percentage !== 0 && <Text style={styles.percentage}>{percentage}%</Text>}
{image &&
image.map((img) => (
<View>
<Text style={styles.result} onPress={copyToClipboard}>
<Image
source={{ uri: img }}
style={{ width: 250, height: 250 }}
/>
</Text>
<Text style={styles.info}>Long press to copy the image url</Text>
</View>
))}
<Button onPress={pickImage} title="Pick an image from camera roll" />
</View>
);
};
export default UploadImageAWS;
CodePudding user response:
Running a loop on the handleImagePicked function
then having a random name being generated for each picture solved the problem. Here's what the code looks like
imports
import { v4 as uuidv4 } from "uuid";
import * as ImagePicker from "expo-image-picker";
methods logic
let imagesArray = [];
const pickImage = async () => {
let result = await ImagePicker.launchImageLibraryAsync({
mediaTypes: "Images",
aspect: [4, 3],
quality: 1,
allowsMultipleSelection: true,
});
result.assets.forEach((image) => handleImagePicked(image));
};
const handleImagePicked = async (pickerResult) => {
const imageName = uuidv4();
try {
if (!pickerResult.canceled) {
const img = await fetchImageFromUri(pickerResult.uri);
const uploadUrl = await uploadImage(imageName, img);
console.log("upload url = ", uploadUrl);
downloadImage(uploadUrl);
}
} catch (e) {
console.log("Upload failed", e.message);
}
};
const uploadImage = async (filename, img) => {
Auth.currentCredentials();
return Storage.put(filename, img, {
level: "public",
contentType: "image/jpeg",
})
.then((response) => {
return response.key;
})
.catch((error) => {
console.log(error);
return error.response;
});
};
const downloadImage = (uri) => {
Storage.get(uri)
.then((result) => {
setImages(result);
imagesArray.push(result);
})
.catch((err) => console.log(err));
};
const fetchImageFromUri = async (uri) => {
const response = await fetch(uri);
const blob = await response.blob();
// console.log("blob of URI : " JSON.stringify(blob));
return blob;
};
Images display
<FlatList
horizontal
showsHorizontalScrollIndicator={false}
data={imagesArray}
renderItem={({ item }) => (
<Image
source={{ uri: item }}
style={{
height: 75,
width: 75,
borderRadius: 10,
marginHorizontal: 10,
resizeMode: "contain",
}}
/>
)}
/>