在 Android 上的 React-Native 中压缩 base64 编码的图像无法识别'data'协议



essue

在反应本地(0.43(应用程序中,我们使用的组件使用截面列表来渲染按天排序的照片。每个部分都可以包含多个图像。使用 React-Native-nimimage-crop-picker 库拍摄照片,并将其上传到后端,或者如果没有Internet连接,以Base64格式编码,则在本地排队。图像分辨率设置为800x800像素(用于图像的其他目的(。在具有较低内存的手机上,由于内存不足,渲染约20张图像将崩溃该应用。这个问题只能在低端Android手机上复制,但我希望这是一个低的内存问题,并且与OS无关。要解决此问题,需要生成缩略图以测试是否是这种情况。独立于生成这些缩略图的时间(在加载组件之前发送到服务器或即时发送(。下面的代码适用于iOS,但对于Android,它引发了错误:未知协议:数据来自 imageeditor.cropimage((函数。函数。

摘要来自main .js文件

//The mergeReduxWithMeteor function takes care of merging the redux state, 
//containing images not yet uploaded to the server, 
//and the Meteor data as received by the server.
//No issues here...
helpers.mergeReduxWithMeteor(props.photoStore, props.SynergySummaryReady ? props.SynergyData : [])
  //The imageHelper.compressPhoto does the actual compression
  //No issues with the promise chain as is.
  .then((data) => {
    return Promise.all(data.map(imageHelper.compressPhoto))
  })
  // The remaining functions take care of the formatting for the SectionList.
  // No issues here either... :)
  .then((data) => {
    return helpers.clusterDataByDay(data)
  })
  //We populate the resulting data in the state that is used for the SectionList
  .then((data) => {
    this.setState({NotHorusData: data})
  })
  .catch((error) => console.error(error))

imageHelper.compressphoto((

export function compressPhoto(photo) {
  return new Promise((resolve, reject) => {
    let imageSize = {
      offset: {
        x: 0,
        y: 0
      },
      size: {
        width: IMAGE_SIZE,
        height: IMAGE_SIZE
      },
      displaySize: {
        width: IMAGE_TARGET_SIZE,
        height: IMAGE_TARGET_SIZE,
      },
      resizeMode: 'contain'
    }

    ImageEditor.cropImage(`data:image/jpeg;base64,${photo.data.userPhoto}`, imageSize, (imageURI) => {
      ImageStore.getBase64ForTag(imageURI, (base64Data) => {
        resolve({
          ...photo,
          data: {
            ...photo.data,
            userPhoto: base64Data,
          }
        })
      }, (error) => reject(error))
    }, (error) => reject(error))
  })
}

方法1:修复Android上的数据协议问题

RN的GitHub上的问题解决了同一问题,但没有提供解决方案。

方法2:通过在Android上提供URI

来绕过数据协议问题

尽管由于增加了通信/延迟,但另一种方法是通过提供Imagestore提供的临时URI来避免数据协议问题。请参阅下面的Android代码。

if(Platform.OS === 'android'){
  ImageStore.addImageFromBase64(`data:image/jpeg;base64,${photo.data.userPhoto}`, (tempURI) => {
    ImageEditor.cropImage(tempURI, imageSize, (imageURI) => {
         ImageStore.getBase64ForTag(imageURI, (base64Data) => {
           ImageStore.removeImageForTag(tempURI)
           resolve({
             ...photo,
             data: {
               ...photo.data,
               userPhoto: base64Data,
             }
           })
       }, (error) => reject(error))
     }, (error) => reject(error))
  }, (error) => reject(error))  
}

不幸的是 Imagestore.AddimageFrombase64 在Android上未识别。

有人在Android上有 ImageDitor Imagestore 在这种情况下可能会有所帮助吗?也欢迎其他任何方法!

我设法通过使用 react-native-native-fetch-blob react-nive-nimative-image-image-resizer 来解决问题对于iOS和Android。与上述问题中的实现相比,性能是出乎意料的。我分享了以下代码供其他人使用:(

export function compressPhoto(photo) {
    return new Promise((resolve, reject) => {
        let tempUri = `${cache}/Vire_${photo.data.userPhotoDate}.jpg`
        fs.writeFile(tempUri, photo.data.userPhoto, "base64")
            .then(() => {
                ImageResizer.createResizedImage(
                    `file:${tempUri}`, IMAGE_TARGET_SIZE, IMAGE_TARGET_SIZE, "JPEG", 100, 0).then((resizedImageUri) => {
                    fs.readFile(`${resizedImageUri}`, "base64")
                        .then( data => {
                            resolve({...photo, data: { ...photo.data, userPhoto: data }})
                        })
                        .catch(error => reject(`readFile:error: ${error}`))
                },
                (error) => reject(`createResizedImage:error: ${error}`)
                )
            })
            .catch( error => {
                reject(`writeFile:error: ${error}`)
            })
            
  })
}

GIST将Base64编码图片存储在高速座中,并使用成像器获取图像,压缩图像并在Base64中再次读取。

最新更新