Home > Net >  How can I upload multiple Images to AWS using Expo Image Picker
How can I upload multiple Images to AWS using Expo Image Picker

Time:12-04

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",
                  }}
                />
              )}
            />
  • Related