将本机内容 uri 反应为 base64 字符串

React native content uri to base64 string

我正在尝试使用 RN Document Picker 上传文件。

选择这些文件后,我需要将它们转换为 base64 字符串,以便将其发送到我的 API。

const handlePickFiles = async () => {
      if (await requestExternalStoreageRead()) {
        const results = await DocumentPicker.pickMultiple({
          type: [
            DocumentPicker.types.images,
            DocumentPicker.types.pdf,
            DocumentPicker.types.docx,
            DocumentPicker.types.zip,
          ],
        });
        const newUploadedFile: IUploadedFile[] = [];

        for (const res of results) {
          console.log(JSON.stringify(res, null, 2));

          newUploadedFile.push({
            name: res.name,
            type: res.type as string,
            size: res.size as number,
            extension: res.type!.split('/')[1],
            blob: res.uri, <<-- Must turn this in base64 string
          });
        }
        setUploadedFiles(newUploadedFile);
        console.log(newUploadedFile);
      }
    }
  };

文档选择器 returns 内容 uri (content://...) 他们将此列为处理 blob 数据和 base64 的示例:

let data = new FormData()
data.append('image', {uri: 'content://path/to/content', type: 'image/png', name: 'name'})
const response = await fetch(url, {
      method: 'POST',
      headers: {
        'Content-Type': 'multipart/form-data',
      },
      body: data
    })

他们基本上说在使用 multipart/form-data 作为内容类型时不需要使用 blob 或 base64。但是,我的 graphql 端点无法处理多部分数据,我没有时间重写整个 API。我只想将其转换为 blob 和 base64 字符串,即使其他方式性能更高。

正在搜索其他库,全部不再维护,或者新版本android有问题。 RN Blob Utils 是不再维护的最新 npm。

我尝试使用 RN Blob Utils,但我收到错误、数据类型错误或文件上传但已损坏。

我发现的其他一些东西我可以使用

fetch(res.uri).then(response => {response.blob()})
          const response = await ReactNativeBlobUtil.fetch('GET', res.uri);
          const data = response.base64();
ReactNativeBlobUtil.wrap(decodeURIComponent(blob))        
///----
const blob = ReactNativeBlobUtil.fs.readFile(res.uri, 'base64');

但我无法对该 blob 文件执行任何操作。

将文档选择器中的文件上传为 base64 格式的最简单方法是什么?是否可以避免使用外部存储权限?

不需要第三方包来获取BLOB数据

 const blob = await new Promise((resolve, reject) => {
    const xhr = new XMLHttpRequest();
    xhr.onload = function () {
      resolve(xhr.response);
    };
    xhr.onerror = function (e) {
      reject(new TypeError("Network request failed"));
    };
    xhr.responseType = "blob";
    xhr.open("GET", "[LOCAL_FILE_PATH]", true);
    xhr.send(null);
  });

  // Code to submit blob file to server

  // We're done with the blob, close and release it
  blob.close();

我最终使用了 react-native-blob-util

const res = await DocumentPicker.pickSingle({
              type: [
                DocumentPicker.types.images,
                DocumentPicker.types.pdf,
                DocumentPicker.types.docx,
                DocumentPicker.types.zip,
              ],
            });
            const newUploadedFile: IUploadedFile[] = [];

            const fileType = res.type;
            if (fileType) {
              const fileExtension = fileType.substr(fileType.indexOf('/') + 1);
              const realURI = Platform.select({
                android: res.uri,
                ios: decodeURI(res.uri),
              });
              if (realURI) {
                const b64 = await ReactNativeBlobUtil.fs.readFile(
                  realURI,
                  'base64',
                );
                const filename = res.name.replace(/\s/g, '');
                const path = uuid.v4();
                newUploadedFile.push({
                  name: filename,
                  type: fileType,
                  size: res.size as number,
                  extension: fileExtension,
                  blob: b64,
                  path: Array.isArray(path) ? path.join() : path,
                });
              } else {
                throw new Error('Failed to process file');
              }
            } else {
              throw new Error('Failed to process file');
            }