RNFetchBlob 无法上传图片

RNFetchBlob is not working to upload image

我正在尝试为我的 Firebase 云存储创建一个上传功能。我正在使用 RNFetchBlob 以及 react-native-image-picker。我可以 select 照片,但不会上传。所有其他 Firebase 功能都很好用,它是通过 React-Native-Firebase 安装的...

'fs.readFile'之后似乎没有发生任何事情。

import React, { Component } from 'react'
import {
  StyleSheet,
  Text,
  View,
  TouchableOpacity,
  Platform,
  Image,
  ActivityIndicator
} from 'react-native'
import ImagePicker from 'react-native-image-picker'
import RNFetchBlob from 'rn-fetch-blob'
import firebase from 'react-native-firebase';


const storage = firebase.storage()

// Prepare Blob support
const Blob = RNFetchBlob.polyfill.Blob
const fs = RNFetchBlob.fs
window.XMLHttpRequest = RNFetchBlob.polyfill.XMLHttpRequest
window.Blob = Blob

const uploadImage = (uri, mime = 'application/octet-stream') => {
  return new Promise((resolve, reject) => {
    const uploadUri = Platform.OS === 'ios' ? uri.replace('file://', '') : uri
    const sessionId = new Date().getTime()
    let uploadBlob = null
    const imageRef = storage.ref('images').child('${sessionId}')

    fs.readFile(uploadUri, 'base64')
      .then((data) => {
        return Blob.build(data, { type: '${mime};BASE64' })

      })
      .then((blob) => {
        uploadBlob = blob
        return imageRef.put(blob, { contentType: mime })

      })
      .then(() => {
        uploadBlob.close()
        return imageRef.getDownloadURL()
      })
      .then((url) => {
        resolve(url)
      })
      .catch((error) => {
        reject(error)
    })
  })
}


class Demo extends Component {
  constructor(props) {
    super(props)

    this.state = {}
  }

  _pickImage() {
    this.setState({ uploadURL: '' })

    ImagePicker.launchImageLibrary({}, response  => {
      uploadImage(response.uri)
        .then(url => this.setState({ uploadURL: url }))
        .catch(error => console.log(error))
    })
  }

  render() {
    return (
      <View style={ styles.container }>
        {
          (() => {
            switch (this.state.uploadURL) {
              case null:
                return null
              case '':
                return <ActivityIndicator />
              default:
                return (
                  <View>
                    <Image
                      source={{ uri: this.state.uploadURL }}
                      style={ styles.image }
                    />
                    <Text>{ this.state.uploadURL } {this.state.uploadURL}</Text>
                  </View>
                )
            }
          })()
        }
        <TouchableOpacity onPress={ () => this._pickImage() }>
          <Text style={ styles.upload }>
            Upload
          </Text>
        </TouchableOpacity>
      </View>
    )
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#F5FCFF',
  },
  image: {
    height: 200,
    resizeMode: 'contain',
  },
  upload: {
    textAlign: 'center',
    color: '#333333',
    padding: 10,
    marginBottom: 5,
    borderWidth: 1,
    borderColor: 'gray'
  },
})

export default Demo

我在 select 拍摄照片时在我的控制台中收到此错误:

filePath.replace is not a function. (In 'filePath.replace('file://', '')', 'filePath.replace' is undefined)]

只需将图像 url 直接传递给 storage ref。您不再需要创建 blob 文件。我猜 firebase 现在在内部处理它。

这是我刚刚与 react-native-image-crop-picker 一起测试的示例:

import firebase from 'react-native-firebase';
import ImagePicker from 'react-native-image-crop-picker';

export default class ImageUploadService {
  static init() {}

  static openPickerAndUploadImage() {
    const uid = '12345';

    ImagePicker.openPicker({
      width: 300,
      height: 300,
      cropping: true,
      mediaType: 'photo',
    })
      .then(image => {
        const imagePath = image.path;

        const imageRef = firebase
          .storage()
          .ref(uid)
          .child('dp.jpg');
        let mime = 'image/jpg';

        imageRef
          .put(imagePath, { contentType: mime })
          .then(() => {
            return imageRef.getDownloadURL();
          })
          .then(url => {
            // You could now update your users avatar for example
            //firebase.database().ref('users').child(uid).update({ ...userData})
            console.log('URL', url);
          });
      })
      .catch(error => {
        console.log(error);
      });
  }
}

ImageUploadService.init();

现在只需在您的组件之一中调用 ImageUploadService.openopenPickerAndUploadImage() 即可。

我相信这也适用于 react-native-image-picker,只需删除代码中的 blob 部分并将图像 url 直接传递给您的 imageRef.put

==>

const uploadImage = (uri, mime = 'application/octet-stream') => {
  return new Promise((resolve, reject) => {
    const imagePath = uri;

    const imageRef = firebase
      .storage()
      .ref('images')
      .child('dp.jpg');
    let mime = 'image/jpg';

    imageRef
      .put(imagePath, { contentType: mime })
      .then(() => {
        return imageRef.getDownloadURL();
      })
      .then(resolve)
      .catch(reject);
  });
};