You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用apollo-upload-client上传文件时App崩溃及Blob上传异常

问题解决:React Native 结合 Apollo 上传文件的两类异常处理

一、解决okhttp3.internal.Util类找不到问题

1. 统一OkHttp版本

React Native 0.68.1自带的OkHttp版本可能与apollo-upload-client依赖版本冲突,导致内部类缺失。在项目根目录的android/build.gradle中强制指定兼容版本:

allprojects {
    configurations.all {
        resolutionStrategy.force 'com.squareup.okhttp3:okhttp:4.9.3'
        resolutionStrategy.force 'com.squareup.okhttp3:logging-interceptor:4.9.3'
    }
}

2. 修复ProGuard混淆规则

若开启代码混淆,需确保ProGuard未移除OkHttp内部类。在android/app/proguard-rules.pro中添加:

-keep class okhttp3.** { *; }
-keep interface okhttp3.** { *; }
-dontwarn okhttp3.internal.**

3. 清理缓存重建项目

执行命令清理RN和Android构建缓存:

# 重置RN缓存
npx react-native start --reset-cache

# 清理Android构建文件
cd android && ./gradlew clean && cd ..

二、解决Blob上传后端接收file为null问题

1. 替换RN原生Blob实现,适配Apollo上传逻辑

RN的Blob与Web端实现存在差异,apollo-upload-client对其支持有限。使用react-native-file-access读取文件并构建兼容的上传对象:
先安装依赖:

npm install react-native-file-access

修改上传逻辑:

import { FileSystem } from 'react-native-file-access';

// ... 其他代码
const uploadFile = async (fileUri, fileName, mimeType) => {
  // 读取文件为ArrayBuffer
  const base64Data = await FileSystem.readFile(fileUri, 'base64');
  const arrayBuffer = Uint8Array.from(atob(base64Data), c => c.charCodeAt(0));
  
  // 构建Apollo可识别的文件对象
  const file = {
    uri: Platform.OS === 'android' && !fileUri.startsWith('file://') ? `file://${fileUri}` : fileUri,
    name: fileName,
    type: mimeType,
    blob: new Blob([arrayBuffer], { type: mimeType })
  };

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

2. 检查Apollo客户端配置

确保使用createUploadLink替代普通createHttpLink,开启文件上传支持:

import { ApolloClient, InMemoryCache } from '@apollo/client';
import { createUploadLink } from 'apollo-upload-client';

const client = new ApolloClient({
  link: createUploadLink({
    uri: '你的后端GraphQL地址',
    headers: {
      // 自定义请求头,如Authorization
    }
  }),
  cache: new InMemoryCache(),
});

3. 抓包对比请求差异

用Charles或Fiddler抓取RN上传请求,与Postman请求对比:

  • 检查FormData的字段名是否与后端接收参数file一致
  • 验证Content-Type是否为multipart/form-data且包含正确的边界标识

额外排查建议

  • 确认后端GraphQL解析器已正确配置文件上传(如使用graphql-upload)
  • 尝试降级apollo-upload-client至v10.x版本,适配RN 0.68的旧环境

内容的提问来源于stack exchange,提问作者daniel meyer

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 11:33:18