javascript 如何上传一个blob到firebase存储?

huus2vyu  于 2023-01-29  发布在  Java
关注(0)|答案(1)|浏览(169)

我正在使用带有firebase v9的next js 13.并且我正在使用一个拖放区来上传图像.拖放区返回一个带有blob的数组,因为它是src.

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

上面的数组是从drop zone返回的。当我试图上传到firebase存储时,它抛出了一个错误。

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

那么我怎样才能上传blob图像到firebase存储呢?

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,
    });
  };

丢弃区域代码

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;
      });
    },
})

并且滴落区的输出为

8i9zcol2

8i9zcol21#

正如评论中提到的,您需要实际的FileBlob对象来上传文件,而不是对象URL。您可以如下所示设置blob的状态:

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

然后上传文件并将下载URL存储在Firestore文档中,请尝试以下功能:

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);
};

您可以在单击提交按钮时调用此函数,也可以在希望开始上载时调用任何事件。

相关问题