将图像路径转换为 ​​blob react native

Posted

技术标签:

【中文标题】将图像路径转换为 ​​blob react native【英文标题】:Convert image path to blob react native 【发布时间】:2018-06-14 23:34:02 【问题描述】:

问题

我正在尝试使用 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);
  ;


我已经尝试添加注释代码,它不会上传任何东西,我已经尝试了现在的代码,这给了我错误Can currently only create a Blob from other Blobs,并且上传进度永远不会超过0%。

【问题讨论】:

可能是this 会帮助你。他正在附加图像 uri。 【参考方案1】:

如果您使用的是 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);

参考:https://youtu.be/KkZckepfm2Q

【讨论】:

谢谢!我认为这是最简单的解决方案。 它有时会无缘无故地给出网络错误。有时它就像一个 chram【参考方案2】:

参考此链接 - https://github.com/dailydrip/react-native-firebase-storage/blob/master/src/App.js#L43-L69

以下代码块工作正常。

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

【讨论】:

不幸的是不兼容博览会【参考方案3】:

需要安装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

【讨论】:

仅供参考,对于想要将图像上传到不使用 expo 的 firebase 存储的任何人(就像我不是),您可以将图像 uri 作为第一个参数传递给 ref。放()函数。即 ref.put(uri) @K.Wu 。当我添加“window.Blob = Blob;”时,我正在尝试在空对象引用异常上调用接口方法'java.lang.String.facebook.react.bridge.readablemap.getstring(java.lang.string),如果我删除这个没有例外,但 blob 格式不正确。请帮忙 @AndrewIrwin 也许在您写该评论时是可能的,但现在 put 方法需要一个 Blob 或文件。传递 URI 字符串将导致抛出错误。 在这种情况下window 是什么? react-native 中没有原生窗口对象... Blob.build 中缺少“then”....((url) =&gt; 【参考方案4】:

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

在这种情况下,使用 fetch(uri) 并不能帮助我获得 blob。

但如果您使用fetch(uri.replace("file:///","file:/")) 然后按照@sriteja Sugoor 的回答,您将能够上传文件blob。

【讨论】:

【参考方案5】:
const Blob = RNFetchBlob.polyfill.Blob;
      const fs = RNFetchBlob.fs;
      let uploadBlob;
      await fs
        .readFile(params?.file.path, 'base64')
        .then((data) => 
          return Blob.build(data, type: `BASE64`);
        )
        .then((blob) => 
          uploadBlob = blob;
          console.log(uploadBlob, 'uploadBlob');
        );

【讨论】:

以上是关于将图像路径转换为 ​​blob react native的主要内容,如果未能解决你的问题,请参考以下文章

React-native - 使用已转换为 URL 的 Blob 填充图像

如何将 blob 图像从数据库转换为 html 图像 src

将画布转换为 blob 时如何保持图像大小

将blob图像转换为数组以显示在spring mvc的网页中

如何将实时图像 url 转换为角度的 blob? [复制]

如何使用 Spring 将 blob 转换为图像