apollo上传客户端使用ReactNativeFile上传文件时App崩溃

问题描述 投票:0回答:1

问题描述

我在尝试使用 ReactNativeFile 和 apollo-upload-client 上传文件时遇到与 okhttp3.internal.Util 相关的 ClassNotFoundException。此外,当使用 Blob 实例时,后端会收到一个空文件参数,尽管在使用 Postman 测试时文件上传工作正常。

重现步骤

  1. 使用 DocumentPicker 选择文档(例如 PDF、DOC、DOCX 或图像)。
  2. 将所选文件的 URI 转换为 Blob 实例。
  3. 使用 Blob 实例创建一个 File 对象,并尝试使用 Apollo 的 uploadImageMutation 上传它。

使用ReactNativeFile:

const handleDocumentSelection = async () => {
  try {
    const res = await DocumentPicker.pick({
      type: [
        DocumentPicker.types.pdf,
        DocumentPicker.types.doc,
        DocumentPicker.types.docx,
        DocumentPicker.types.images,
      ],
      copyTo:
        Platform.OS === 'android' ? 'cachesDirectory' : 'documentDirectory',
    });

    const uploadFile = async (fileUri, fileName, mimeType) => {
      const file = new ReactNativeFile({
        uri: fileUri,
        name: 'picture.jpg',
        type: mimeType
      });

      console.log('File object to be uploaded:', file);

      try {
        const { data } = await uploadImageMutation({
          variables: { file },
        });
        console.log('Upload response:', data);
      } catch (error) {
        console.error('Upload error:', error);
      }
    };

    const { fileCopyUri, name, type } = res[0];
    uploadFile(fileCopyUri, name, type);
  } catch (err) {
    if (DocumentPicker.isCancel(err)) {
      // Handle cancel
    } else {
      throw err;
    }
  }
};

### 使用 Blob 实例:

const handleDocumentSelection = async () => {
  try {
    const res = await DocumentPicker.pick({
      type: [
        DocumentPicker.types.pdf,
        DocumentPicker.types.doc,
        DocumentPicker.types.docx,
        DocumentPicker.types.images,
      ],
      copyTo:
        Platform.OS === 'android' ? 'cachesDirectory' : 'documentDirectory',
    });

    const convertUriToBlob = async (uri, mimeType) => {
      const base64Data = await RNFetchBlob.fs.readFile(uri, 'base64');
      const byteCharacters = atob(base64Data);
      const byteNumbers = new Array(byteCharacters.length);
      for (let i = 0; i < byteCharacters.length; i++) {
        byteNumbers[i] = byteCharacters.charCodeAt(i);
      }
      const byteArray = new Uint8Array(byteNumbers);
      return new Blob([byteArray], { type: mimeType });
    };

    const uploadFile = async (fileUri, fileName, mimeType) => {
      const fileBlob = await convertUriToBlob(fileUri, mimeType);

      // Create a file object with a Blob instance
      const file = new File([fileBlob], fileName, { type: mimeType });

      console.log('File object to be uploaded:', file);

      try {
        const { data } = await uploadImageMutation({
          variables: { file },
        });
        console.log('Upload response:', data);
      } catch (error) {
        console.error('Upload error:', error);
      }
    };

    const { fileCopyUri, name, type } = res[0];
    uploadFile(fileCopyUri, name, type);
  } catch (err) {
    if (DocumentPicker.isCancel(err)) {
      // Handle cancel
    } else {
      throw err;
    }
  }
};

### 崩溃日志

原因:java.lang.ClassNotFoundException:未找到类 路径上的“okhttp3.internal.Util”:DexPathList[[zip 文件 “/data/app/~~6kd2JTp1gbPoLfrIrCABCA==/care.heyme.mobile-MkqSROqHXIAMbKVAbAvP-w==/base.apk”],nativeLibraryDirectories=[/data/app/~~6kd2JTp1gbPoLfrIrCABCA==/care.heyme.mobile- MkqSROqHXIAMbKVAbAvP-w==/lib/arm64, /data/app/~~6kd2JTp1gbPoLfrIrCABCA==/care.heyme.mobile-MkqSROqHXIAMbKVAbAvP-w==/base.apk!/lib/arm64-v8a、/system/lib64、/product_h/lib64、/system_ext/lib64]]

系统信息

macOS:14.1.1 节点:16.0.0 npm:7.10.0 反应本机:0.68.1 阿波罗上传客户端:11.0.0 Android SDK:API 级别 30、31、33、34、35 Android 工作室:2024.1 Java:17.0.11

### 附加信息

尽管使用了最新版本的 apollo-upload-client,问题仍然存在。 使用 Blob 实例时,后端收到空文件参数,但在 Postman 中上传正常。

请求帮助

任何人都可以协助解决这个问题吗?是否存在可以解决此 ClassNotFoundException 和 Blob 实例问题的已知兼容性问题或配置设置?

复制步骤

  1. 使用 DocumentPicker 选择文档(例如 PDF、DOC、DOCX 或图像)。
  2. 将所选文件的 URI 转换为 Blob 实例。
  3. 使用 Blob 实例创建一个 File 对象,并尝试使用 Apollo 的 uploadImageMutation 上传它。

@apollo/client
版本

3.8.7

laravel react-native apollo-client lighthouse
1个回答
0
投票

解决方案:

1/需要在 app/build.gradle 中实现 Okhttp :

 implementation 'com.squareup.okhttp3:okhttp:3.8.0'
 implementation 'com.squareup.okhttp3:okhttp-urlconnection:3.8.0'

2/ 还强制使用此版本:3.8.0 在 android/build.gradle 中,如下所示:

allprojects {
     configurations.all {
        resolutionStrategy {
            force 'com.squareup.okhttp3:okhttp:3.8.0'
            force 'com.squareup.okhttp3:okhttp-urlconnection:3.8.0'
        }
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.