Загрузка изображения в Firebase в React Native

У меня есть два пути изображения в моем состоянии компонента

введите описание изображения здесь

Я пытаюсь загрузить одно из изображений внутри функции, но получаю сообщение об ошибке:

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. Спасибо!

4 ответа

Решение

Ошибка говорит о том, что вам нужно использовать BLOB-объект. Вы можете использовать response-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

Я публикую свой код, так как это немного расстраивает меня:

Для загрузки изображений в firebase.storage вам необходимо загрузить изображения в виде BLOB-объектов. Если вы не знаете, что такое капли, не волнуйтесь.

Шаг 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.
})

Вы можете использовать response-native-firebase для загрузки изображения в storge https://rnfirebase.io/

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

Пока что это лучший метод, который я нашел для загрузки файла / изображения в хранилище Firebase с помощью React Native. Этот метод не использует сторонние библиотеки, кроме 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. Создайте BLOB из изображения URI. Есть много сторонних библиотек, которые могут помочь в этом. Но если вы не хотите устанавливать библиотеку, вы можете использовать XMLHttpRequest. Документация React Native рекомендует использовать API Fetch, но сейчас мы не можем его использовать, потому что он выдаст ошибку, которую мы можем только извлечь 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.

    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 Storage. Ключевой частью этого является получение URI файла и преобразование его в BLOB. Вы можете прочитать больше об этом методе здесь.

Некоторое время я использовал Firebase JS SDK с React Native. Используя эту библиотеку, как указано в этом потоке, вам нужно использовать библиотеку, подобную rn-fetch-blob (response-native-fetch-blob больше не поддерживается), чтобы предоставить blob для метода Firebase Storage put().

Недавно я начал использовать React Native Firebase. Как говорится на их веб-сайте: "Использование родных SDK Firebase с React Native Firebase позволяет использовать SDK устройств, которых нет в Firebase JS SDK".

Используя React-Native-Firebase, вам не нужна дополнительная библиотека для загрузки изображений в Firebase Storage, и ваш код становится намного чище:

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

Если вы не возражаете против использования 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

Другие вопросы по тегам