【问题标题】:Uploading Image to Firebase in React Native在 React Native 中将图像上传到 Firebase
【发布时间】:2017-07-02 04:02:20
【问题描述】:

我的组件状态中有两个图像路径

我尝试在函数中上传其中一张图片,但出现错误:

Firebase Storage: Invalid argument in 'put' at index 0: Expected Blob or file

和我的功能

submitImages = () => {

    // Upload images to Firebase storage
    let user = firebaseAuth.currentUser;
    let imagesRef = storageRef.child('productImages/' + user.uid);
    imagesRef.put(this.state.imageFront).then(snapshot => {
        console.log('Uploaded ' + this.state.imageFront);
    });
}

我应该怎么做才能将这些图像上传到 Firebase。谢谢!

【问题讨论】:

标签: firebase react-native firebase-storage


【解决方案1】:

错误说明您需要使用 blob。你可以使用 react-native-fetch-blob:https://github.com/wkh237/react-native-fetch-blob

看看这个例子:https://github.com/dailydrip/react-native-firebase-storage/blob/master/src/App.js#L43-L69

【讨论】:

  • 嘿,blob 在 EXPO 中不起作用。有没有其他办法?
  • 不使用 EXPO 可能是唯一的方法?我认为 EXPO 在这方面是有限的。想知道他们是否有一些图书馆可以帮助我们。如果没有,请不要使用它。
  • 如果您使用 expo,请查看此链接:forums.expo.io/t/expo-and-uploading-image-blobs/227/20
  • 我早就放弃了世博会。它与我使用的一半 deps 不兼容。
【解决方案2】:

我发布我的代码,因为这对我来说有点令人沮丧:

要将图像上传到 firebase.storage,您需要将图像作为 Blob 上传。如果您不知道 Blob 是什么,请不要担心:BLOB 代表 Binary Large OB喷射。

第 1 步。

npm install --save react-native-fetch-blob

第 2 步。

// copy and paste this code where you will handle the file upload

import RNFetchBlob from 'react-native-fetch-blob'

const Blob = RNFetchBlob.polyfill.Blob;
const fs = RNFetchBlob.fs;
window.XMLHttpRequest = RNFetchBlob.polyfill.XMLHttpRequest;
window.Blob = Blob;

第 3 步。

// The uploadImage function that you are going to use:

function uploadImage(uri, mime = 'image/jpeg', name) {
  
  return new Promise((resolve, reject) => {
    let imgUri = uri; let uploadBlob = null;
    const uploadUri = Platform.OS === 'ios' ? imgUri.replace('file://', '') : imgUri;
    const { currentUser } = firebase.auth();
    const imageRef = firebase.storage().ref(`/jobs/${currentUser.uid}`)

    fs.readFile(uploadUri, 'base64')
      .then(data => {
        return Blob.build(data, { type: `${mime};BASE64` });
      })
      .then(blob => {
        uploadBlob = blob;
        return imageRef.put(blob, { contentType: mime, name: name });
      })
      .then(() => {
        uploadBlob.close()
        return imageRef.getDownloadURL();
      })
      .then(url => {
        resolve(url);
      })
      .catch(error => {
        reject(error)
    })
  })
}

那么你如何调用这个函数呢? 将图像的 URI 作为第一个参数传递。在我的情况下,img1, img2, img3 指向图像 URI 的变量,我想上传在我的手机上。它们看起来像 '/Phone/Pics/imageToUpload.jpeg' 等。

作为第二个参数,您可以传递'image/jpeg',最后一个参数是您要为图像指定的名称。选择你喜欢的名字。

但是,如果我有几张图片并且想要上传它们并且想要正确处理上传怎么办。如果一个上传成功而另一个没有上传怎么办?

然后这样做:

let imgPromises = [];
imgPromises.push(uploadImage(img1, 'image/jpeg', 'imageOne'));
imgPromises.push(uploadImage(img2, 'image/jpeg', 'imageTwo'));
imgPromises.push(uploadImage(img3, 'image/jpeg', 'imageOne'));

Promise.all(imgPromises).then(urls => {
  // ALL IMAGES SUCCEEDED and you will get an array of URIS that you can save to your database for later use!
}).catch(error => {
  // One OR many images failed the upload. Give feedback to someone.
})

【讨论】:

  • React Native 中有 window 吗?
  • @ridoansaleh 是的
  • 如何导入?......import { window } from 'react-native'; ?当我运行代码时,我得到“无法设置未定义的属性'XMLHttpRequest'”(指窗口)
  • 嗯,这很奇怪。你不需要导入它。 console.log RNFetchBlob.polyfill 并检查 XMLHttpRequest 是否已定义。
【解决方案3】:

如果您不介意使用 cloudinary,我将展示如何上传然后获取上传的 url 以保存到 firebase https://medium.com/@ifeoluwaking24/how-to-upload-an-image-in-expo-react-native-to-firebase-using-cloudinary-24aac981c87

您也可以尝试小吃,但请确保添加您的 cloud_name 和 upload_preset https://snack.expo.io/@ifeking/upload-to-cloudinary

【讨论】:

    【解决方案4】:

    您可以使用 react-native-firebase 上传图片到存储https://rnfirebase.io/

    const storage = firebase.storage();
    const sessionId = new Date().getTime();
    const imageRef = storage.ref('images').child(`${sessionId}`);
    return imageRef.putFile(uri);
    

    【讨论】:

      【解决方案5】:

      有一段时间我将Firebase JS SDK 与 React Native 一起使用。使用这个库,正如这个线程中提到的,你需要使用像rn-fetch-blob 这样的库(不再维护react-native-fetch-blob),以便为Firebase Storage put() 方法提供一个blob。

      最近我开始使用React Native Firebase。正如他们在他们的网站上所说的“将本机 Firebase SDK 与 React Native Firebase 一起使用,您可以使用 Firebase JS SDK 上不存在的设备 SDK”。

      使用 React-Native-Firebase,您无需任何额外的库即可将图像上传到 Firebase 存储,并且您的代码变得更加简洁:

      export const uploadImage = (path, mime = 'application/octet-stream') => {
        return new Promise((resolve, reject) => {
          const imageRef = firebase.storage().ref('images').child('filename.jpg');
      
          return imageRef.put(path, { contentType: mime })
            .then(() => {
              return imageRef.getDownloadURL();
            })
            .then(url => {
              resolve(url);
            })
            .catch(error => {
              reject(error);
              console.log('Error uploading image: ', error);
            });
        });
      };
      

      【讨论】:

        【解决方案6】:

        到目前为止,这是我发现使用 React Native 将文件/图像上传到 Firebase 存储的最佳方法。此方法不使用除 Expo SDK 之外的任何第三方库。

        1. 获取要上传的图片的文件 URI。为此,我们需要使用Expo ImagePicker。包含此代码块的最佳位置是位于带有 onPress 处理程序的按钮上。

          ImagePicker.launchImageLibraryAsync({ 
            mediaTypes: "Images"
          }).then((result)=>{ 
          
            if (!result.cancelled) {
              // User picked an image
              const {height, width, type, uri} = result;
              return uriToBlob(uri); // will follow later
            }
          
          })
          
        2. 从图像 URI 生成 BLOB。有很多第三方库可以帮助做到这一点。但是如果你不想安装库,那么你可以使用XMLHttpRequest。 React Native 文档recommends we use the Fetch API,但现在我们不能使用它,因为它会抛出一个错误,我们只能获取https:// url,但我们的URI 是file://。有一种方法可以通过这个,但是使用 XMLHttpRequest 会让事情变得简单很多。

          uriToBlob = (uri) => {
          
          return new Promise((resolve, reject) => {
          
            const xhr = new XMLHttpRequest();
          
            xhr.onload = function() {
              // return the blob
              resolve(xhr.response);
            };
          
            xhr.onerror = function() {
              // something went wrong
              reject(new Error('uriToBlob failed'));
            };
          
            // this helps us get a blob
            xhr.responseType = 'blob';
          
            xhr.open('GET', uri, true);
            xhr.send(null);
          
          });
          
          }
          
        3. 我们有我们的 BLOB,让我们将其上传到 Firebase。这部分非常简单,如 Firebase Docs 中所述。

          uploadToFirebase = (blob) => {
          
          return new Promise((resolve, reject)=>{
          
            var storageRef = firebase.storage().ref();
          
            storageRef.child('uploads/photo.jpg').put(blob, {
              contentType: 'image/jpeg'
            }).then((snapshot)=>{
          
              blob.close(); // let's free up the blob
          
              resolve(snapshot);
          
            }).catch((error)=>{
          
              reject(error);
          
            });
          
          });
          
          
          }
          

        就是这样,您现在可以将文件上传到 Firebase 存储。关键部分是获取文件 URI 并将其转换为 BLOB。您可以阅读有关此方法的更多信息here

        【讨论】:

        • 谢谢你。这可能是这篇文章中最好的答案,因为它不使用任何其他库。补充一点,如果人们像我一样愚蠢,请不要忘记 uriToBlob 函数返回一个承诺,即 uriToBlob(response.uri).then(blob => this.setState({photoData: blob})) ;什么的:)
        猜你喜欢
        • 2022-10-18
        • 2021-09-28
        • 2018-01-14
        • 1970-01-01
        • 2020-03-06
        • 2020-06-21
        • 1970-01-01
        • 2020-06-30
        • 2023-03-31
        相关资源
        最近更新 更多