Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/409.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript Firebase存储:字符串与格式base64不匹配:找到无效字符。仅当“调试”处于关闭状态时_Javascript_Firebase_React Native_Firebase Storage_React Native Image Picker - Fatal编程技术网

Javascript Firebase存储:字符串与格式base64不匹配:找到无效字符。仅当“调试”处于关闭状态时

Javascript Firebase存储:字符串与格式base64不匹配:找到无效字符。仅当“调试”处于关闭状态时,javascript,firebase,react-native,firebase-storage,react-native-image-picker,Javascript,Firebase,React Native,Firebase Storage,React Native Image Picker,我正在尝试将图像文件上载到firebase存储,保存下载URL,并在上载完成后加载它。当我远程运行带有debug js的应用程序时,它工作正常。当我关闭调试模式时,它将停止处理无效格式异常。在真实设备(iOS和Android)中运行时也会发生同样的情况 来自React本机映像选择器的base64响应数据似乎是正确的 这是我的密码 ... import * as ImagePicker from 'react-native-image-picker'; //0.26.10 import fireb

我正在尝试将图像文件上载到firebase存储,保存下载URL,并在上载完成后加载它。当我远程运行带有debug js的应用程序时,它工作正常。当我关闭调试模式时,它将停止处理无效格式异常。在真实设备(iOS和Android)中运行时也会发生同样的情况

来自React本机映像选择器的base64响应数据似乎是正确的

这是我的密码

...
import * as ImagePicker from 'react-native-image-picker'; //0.26.10
import firebase from 'firebase'; //4.9.1
...

handleImagePicker = () => {
    const { me } = this.props;
    const options = {
      title: 'Select pic',
      storageOptions: {
        skipBackup: true,
        path: 'images'
      },
      mediaType: 'photo',
      quality: 0.5,
    };
    ImagePicker.showImagePicker(options, async (response) => {
        const storageRef = firebase.storage().ref(`/profile-images/user_${me.id}.jpg`);

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

        const task = storageRef.putString(response.data, 'base64', metadata);
        return new Promise((resolve, reject) => {
          task.on(
            'state_changed',
            (snapshot) => {
              var progress = (snapshot.bytesTransferred / snapshot.totalBytes) * 100;
              console.log('Upload is ' + progress + '% done');
            },
            (error) =>
              console.log(error),
            () => {
              this.onChangeProfileImage();
            }
          );
        });
     }
}

onChangeProfileImage = async () => {
    const { me } = this.props;

    const storageRef = firebase.storage().ref(`/profile-images/user_${me.id}.jpg`);

    const profileImageUrl = await new Promise((resolve, reject) => {
      storageRef.getDownloadURL()
      .then((url) => {
        resolve(url);
      })
      .catch((error) => {
        console.log(error);
      });
    });


  // some more logic to store profileImageUrl in the database

  }
你知道怎么解决这个问题吗


提前感谢。

经过一些研究和调试,我找到了问题的原因和解决方案

为什么会这样? Firebase使用方法对
putstring
方法发送的base64字符串进行解码。 但是,由于JavaScriptCore没有对
atob
btoa
的默认支持,因此无法转换base64字符串,因此会触发异常

当我们在远程调试javascript模式下运行应用程序时,所有javascript代码都在chrome环境下运行,其中支持
atob
btoa
。这就是为什么代码在调试打开时工作,而在调试关闭时不工作

如何解决? 要在React Native中处理
atob
btoa
,我们应该编写自己的编码/解码方法,或者安装一个lib来处理它

在我的情况下,我更喜欢安装lib

但这里有一个编码/解码脚本的示例:

const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
const Base64 = {
  btoa: (input:string = '')  => {
    let str = input;
    let output = '';

    for (let block = 0, charCode, i = 0, map = chars;
    str.charAt(i | 0) || (map = '=', i % 1);
    output += map.charAt(63 & block >> 8 - i % 1 * 8)) {

      charCode = str.charCodeAt(i += 3/4);

      if (charCode > 0xFF) {
        throw new Error("'btoa' failed: The string to be encoded contains characters outside of the Latin1 range.");
      }

      block = block << 8 | charCode;
    }

    return output;
  },

  atob: (input:string = '') => {
    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;
  }
};

export default Base64;
在选择使用自定义脚本或库之后,现在我们必须将以下代码添加到
index.js
文件中:

import { decode, encode } from 'base-64';

if (!global.btoa) {
    global.btoa = encode;
}

if (!global.atob) {
    global.atob = decode;
}

AppRegistry.registerComponent(appName, () => App);
这将在全局范围内声明
atob
btoa
。因此,每当在应用程序中调用这些函数时,React Native将使用全局作用域来处理它,然后从
base-64
lib触发
encode
decode
方法

这就是Base64问题的解决方案

然而,在解决这个问题之后,我发现了另一个问题
Firebase存储:操作的最大重试时间超过了。尝试上载较大的图像时,请重试
。正如所建议的那样,
firebase
似乎有一些限制

我相信,
react native firebase
可能不会在这方面遇到困难,因为它已经准备好以本机方式运行,而不是像
firebase
那样使用web环境。我还没有测试它来确认,但看起来这将是处理它的最佳方法


希望这能对其他人有所帮助。

BTW,@soutot,您是否使用fetch()从缓存中读取文件?它对我不起作用,所以我尝试使用expo的FileSystem.readAsStringAsync。我开始从事其他项目,但没有完成这个项目,所以我没有实现缓存读取。当时我的想法是下载图像并存储在本地存储器中。然后,如果存储了任何有效图像,则从中读取,否则重新获取。我想它可能会起作用。好吧,祝你好运:)fetch似乎对我起了一段时间的作用,然后停止了工作。但是如果将字符串编码为base64字符串,图像的解决方案是什么?
import { decode, encode } from 'base-64';

if (!global.btoa) {
    global.btoa = encode;
}

if (!global.atob) {
    global.atob = decode;
}

AppRegistry.registerComponent(appName, () => App);