Javascript 将图像路径转换为blob react native 问题

Javascript 将图像路径转换为blob react native 问题,javascript,firebase,react-native,firebase-storage,Javascript,Firebase,React Native,Firebase Storage,我正在尝试创建一个带有react native和firebase的应用程序。我希望这个应用程序的一个功能是能够上传图像。不过,我在将图像上载到firebase存储时遇到了一些问题。我正在使用expo的图像选择器查找用户想要上传的图像路径,但一旦找到路径,我不知道如何将其转换为可以上传到firebase的内容 有人能帮我把图像的路径转换成我可以用react native上传到firebase存储的东西吗 我尝试过的 我尝试使用: _pickImage = async () => {

我正在尝试创建一个带有react native和firebase的应用程序。我希望这个应用程序的一个功能是能够上传图像。不过,我在将图像上载到firebase存储时遇到了一些问题。我正在使用expo的图像选择器查找用户想要上传的图像路径,但一旦找到路径,我不知道如何将其转换为可以上传到firebase的内容

有人能帮我把图像的路径转换成我可以用react native上传到firebase存储的东西吗

我尝试过的 我尝试使用:

     _pickImage = async () => {
    let result = await ImagePicker.launchImageLibraryAsync({
      MediaTypeOptions: 'Images',
      quality: 0.4,
_uploadAsByteArray = async (pickerResultAsByteArray, progressCallback) => {

    try {

      var metadata = {
        contentType: 'image/jpeg',
      };

      var storageRef = firebase.storage().ref();
      var ref = storageRef.child('images/'+expoID+'/'+this.state.time)
      let uploadTask = ref.put(pickerResultAsByteArray, metadata)

      uploadTask.on('state_changed', function (snapshot) {

        progressCallback && progressCallback(snapshot.bytesTransferred / snapshot.totalBytes)

        var progress = (snapshot.bytesTransferred / snapshot.totalBytes) * 100;
        console.log('Upload is ' + progress + '% done');

      }, function (error) {
        console.log("in _uploadAsByteArray ", error)
      }, function () {
        var downloadURL = uploadTask.snapshot.downloadURL;
        console.log("_uploadAsByteArray ", uploadTask.snapshot.downloadURL)
    this.setState({imageUploaded:true})
      });


    } catch (ee) {
      console.log("when trying to load _uploadAsByteArray ", ee)
    }
  }


  convertToByteArray = (input) => {
    var binary_string = this.atob(input);
    var len = binary_string.length;
    var bytes = new Uint8Array(len);
    for (var i = 0; i < len; i++) {
      bytes[i] = binary_string.charCodeAt(i);
    }
    return bytes
  }

  atob = (input) => {
    const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';

    let str = input.replace(/=+$/, '');
    let output = '';

    if (str.length % 4 == 1) {
      throw new Error("'atob' failed: The string to be decoded is not correctly encoded.");
    }
    for (let bc = 0, bs = 0, buffer, i = 0;
      buffer = str.charAt(i++);

      ~buffer && (bs = bc % 4 ? bs * 64 + buffer : buffer,
        bc++ % 4) ? output += String.fromCharCode(255 & bs >> (-2 * bc & 6)) : 0
    ) {
      buffer = chars.indexOf(buffer);
    }

    return output;
  }


uploadImage(bsfdata){
    this.setState({imageUploaded:false})
    this._uploadAsByteArray(this.convertToByteArray(bsfdata), (progress) => {
    this.setState({ progress:progress })
    })
  }
  base64:true,
});



 /* if (!result.cancelled) {
      this.setState({ image: result.uri });
      let formData = new FormData();
        formData.append('photo', {
           uri,
           name: `photo.${fileType}`,
           type: `image/${fileType}`,
     });}*/
      this.uploadImage(result.base64);
  };

}
\u pickImage=async()=>{
让结果=等待ImagePicker.launchImageLibraryAsync({
MediaTypeOptions:“图像”,
质量:0.4,
_uploadAsByteArray=async(pickerResultAsByteArray,progressCallback)=>{
试一试{
变量元数据={
contentType:“图像/jpeg”,
};
var storageRef=firebase.storage().ref();
var ref=storageRef.child('images/'+expoID+'/'+this.state.time)
让uploadTask=ref.put(pickerResultAsByteArray,元数据)
uploadTask.on('state_changed',函数(快照){
progressCallback&&progressCallback(snapshot.ByTestTransfered/snapshot.totalBytes)
var progress=(snapshot.bytesttransfered/snapshot.totalBytes)*100;
log('Upload is'+progress+'%done');
},函数(错误){
log(“in\u uploadAsByteArray”,错误)
},函数(){
var downloadURL=uploadTask.snapshot.downloadURL;
console.log(“\u uploadAsByteArray”,uploadTask.snapshot.downloadURL)
this.setState({imageupload:true})
});
}捕获(ee){
log(“当试图加载时,上传asbytearray”,ee)
}
}
convertToByteArray=(输入)=>{
var binary_string=this.atob(输入);
var len=二进制字符串长度;
var字节=新的Uint8Array(len);
对于(变量i=0;i{
常量字符='abcdefghijklmnopqrstuvxyzabcdefghijklmnopqrstuvxyzo123456789+/=';
设str=input.replace(/=+$/,“”);
让输出=“”;
如果(str.length%4==1){
抛出新错误(“'atob'失败:要解码的字符串编码不正确。”);
}
对于(设bc=0,bs=0,buffer,i=0;
buffer=str.charAt(i++);
~buffer&(bs=bc%4?bs*64+buffer:buffer,
bc++%4)?输出+=String.fromCharCode(255&bs>>(-2*bc&6)):0
) {
缓冲区=字符索引(缓冲区);
}
返回输出;
}
上载映像(bsfdata){
this.setState({imageupload:false})
此.u上传AsByteArray(此.convertToByteArray(bsfdata),(进度)=>{
this.setState({progress:progress})
})
}
base64:是的,
});
/*如果(!result.cancelled){
this.setState({image:result.uri});
设formData=new formData();
formData.append('photo'{
乌里,
名称:`photo.${fileType}`,
类型:`image/${fileType}`,
});}*/
这个.uploadImage(result.base64);
};
}

我用添加了注释的代码尝试了它,它没有上载任何内容,我用代码现在的状态尝试了它,这给了我一个错误
当前只能从其他Blob创建Blob
,上载进度永远不会超过0%。

您需要安装
rn fetch Blob
模块:

npm install --save rn-fetch-blob
然后,执行以下操作:

import RNFetchBlob from 'rn-fetch-blob';

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

function uploadImage(path) {
    const imageFile = RNFetchBlob.wrap(path);

    // 'path/to/image' is where you wish to put your image in
    // the database, if you would like to put it in the folder
    // 'subfolder' inside 'mainFolder' and name it 'myImage', just 
    // replace it with 'mainFolder/subfolder/myImage'
    const ref = firebase.storage().ref('path/to/image');
    var uploadBlob = null;

    Blob.build(imageFile, { type: 'image/jpg;' })
        .then((imageBlob) => {
            uploadBlob = imageBlob;
            return ref.put(imageBlob, { contentType: 'image/jpg' });
        })
        .then(() => {
            uploadBlob.close();
            return ref.getDownloadURL();
        })
        .((url) => {
            // do something with the url if you wish to
        })
        .catch(() => {
            dispatch({
                type: UPDATE_PROFILE_INFO_FAIL,
                payload: 'Unable to upload profile picture, please try again'
            });
        });
}
请务必询问代码中是否有您不理解的部分。要上载多个图像,只需使用for循环包装此代码。或者,如果您想确保上传的每个图像都没有任何错误,请使用
Promise

参考此链接-

下面的代码块工作正常。

uploadImage(uri, mime = 'application/octet-stream') {
    return new Promise((resolve, reject) => {
      const uploadUri = Platform.OS === 'ios' ? uri.replace('file://', '') : uri
      let uploadBlob = null

      const imageRef = FirebaseClient.storage().ref('images').child('image_001')

      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)
      })
    })
  }
如果您使用的是expo(>=26),那么您可以使用以下几行代码轻松完成

uploadImage = async(imageUri) => {
  const response = await fetch(imageUri);
  const blob = await response.blob();
  var ref =   firebase.storage().ref().child("image.jpg");
  return ref.put(blob);
}

参考资料:

不确定这对谁有帮助,但如果您正在使用
MediaLibrary
从库中加载图像,则uri的格式为
uri=file:///storage/emulated/0/DCIM/Camera/filename.jpg

在本例中,使用
fetch(uri)
无法帮助我获取blob


但是如果您使用
fetch(uri.replace(“file:///”,“file:/”)
然后按照@sriteja Sugoor的答案进行操作,您将能够上传文件blob。

可能会对您有所帮助。他正在附加图像uri。仅供参考,对于任何想要将图像上载到firebase存储且未使用expo(就像我没有)的人,您可以将图像uri作为第一个参数传递给ref.put()函数。i、 e ref.put(uri)@K.Wu。当我添加“window.Blob=Blob;”时,如果我删除此无异常,但Blob格式不正确,我试图在空对象引用异常上调用接口方法“java.lang.String.facebook.react.bridge.readablemap.getstring(java.lang.String)”。请help@AndrewIrwin也许在编写该注释时是可能的,但现在put方法需要一个Blob或文件。传递URI字符串将导致抛出错误。在这种情况下,
window
是什么?react native中没有本机窗口对象…Blob.build中缺少“then”
((url)=>{
谢谢!我认为这是最简单的解决方案。它有时会无缘无故地出现网络错误。有时它像chramNot expo一样工作