Home > Enterprise >  How to upload a blob into firebase Storage?
How to upload a blob into firebase Storage?

Time:01-29

i'm using next js 13 with firebase v9. and i'm using a drop zone to upload images. the dropzone returns an array with blob as it's src.

[
  {
    id: 1
    name: "image_processing20220628-4591-yzir35.png"
    src: "blob:http://localhost:3000/6e2f33e5-a749-4e9a-b502-d20b8e3f38ca"
  }
 ...
]

the above array is returned from the drop zone. and when i tried to upload to firebase storage it throws an error .

FirebaseError: Firebase Storage: Object 'livingImages/blob:http:/localhost:3000/ca0e3eaf-dbe9-4d77-8053-f4b6d1bd8600' does not exist. (storage/object-not-found)

so how can i upload blob of images to firebase storage?

 const imgURL = [];

 //this is the images stored inside Redux
 const images = useSelector(selectImages); 

  const storage = getStorage();
  images.map(async (file) => {
    const storageRef = ref(storage, `livingImages/${file.src}`);
    await getDownloadURL(storageRef).then((url) => {
      imgURL.push(url);
    });
  });

 const createDocument = () => {
    const docRef = doc(db, "livingPosts", session?.user?.email);
    const colRef = collection(docRef, "posts");
    addDoc(colRef, {
      name: "test upload",
      images: imgURL,
    });
  };

the dropzone code

const dispatch = useDispatch();

  const images = useSelector(selectImages);
  const [files, setFiles] = useState(images == [] ? [] : images);

const {getRootProps, getInputProps} = useDropzone({
onDrop: (acceptedFiles) => {
     acceptedFiles.map((file, index) => {
        const reader = new FileReader();

        reader.onload = async function (e) {
          const options = {
            maxSizeMB: 5,
            maxWidthOrHeight: 1920,
            useWebWorker: true,
          };
          const compressedFile = await imageCompression(file, options);

          const tot = parseInt(acceptedFiles.length)   parseInt(files.length);
          if (tot > 9) {
            alert("select maximum of 9 images");
          } else if (parseInt(acceptedFiles.length) > 9) {
            alert("maximum images to be selected is 9");
          } else if (parseInt(files.length) < 9) {
            setFiles((prevState) => [
              ...prevState,
              {
                id: index,
                src: URL.createObjectURL(compressedFile),
                name: file.name,
              },
            ]);

            files.map((filename) => {
              acceptedFiles.forEach((newFile) => {
                if (newFile.name == filename.name) {
                  alert("a duplicate image is detected");

                  setFiles(
                    files,
                    files.filter((val) => val !== newFile)
                  );
                }
              });
            });
          } else {
            alert("something went wrong");
          }
        };
        reader.readAsDataURL(file);
        return file;
      });
    },
})

and the output of the dropzone is

screenshot

CodePudding user response:

As mentioned in the comments, you'll need the actual File or Blob object to upload the file and not the object URL. You can set the blob in state as shown below:

setFiles((prevState) => [
  ...prevState,
  {
    id: index,
    src: URL.createObjectURL(compressedFile),
    blob: compressedFile, // <-- add blob
    name: file.name,
  },
]);

Then to upload the files and storing download URLs in Firestore document, try the following function:

import { ref, uploadBytes, getDownloadURL } from "firebase/storage";
import { addDoc } from "firebase/firestore";

const uploadFiles = async () => {
  console.log(files);
  const promises = files.map((file) => {
    const storageRef = ref(storage, `images/${file.name}`);
    return uploadBytes(storageRef, file.blob);
  });

  // upload all files
  const res = await Promise.all(promises);

  // get download URLs
  const links = await Promise.all(res.map((r) => getDownloadURL(r.ref)));
  console.log({ links })

  // Add Firestore document
  const colRef = collection(db, "livingPosts", session?.user?.email, "posts")
  const docRef = await addDoc(colRef, {
    name: "test",
    images: links,
  });
  console.log("Document written with ID: ", docRef.id);
};

You can call this function on a submit button click or any event when you want to start the upload.

  • Related