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

使用expo-document-picker的getDocumentAsync移动端无output返回问题

问题排查与解决方案

1. 核心问题:getDocumentAsync 返回结构跨端差异

expo-document-picker在原生移动端和React Native Web的返回格式完全不同:

  • 原生移动端:返回对象直接包含uri、name、mimeType等字段,不存在output数组
  • React Native Web:返回对象包含output数组,内部才是选中的文件对象

你的代码直接判断file.output,在移动端会因条件不成立导致无法设置状态。修改pickDocument函数以兼容两端:

const pickDocument = async () => {
    try {
        const result = await DocumentPicker.getDocumentAsync({
            type: "application/pkcs12",
            copyToCacheDirectory: true, // 确保原生端文件可被访问
        });

        // 兼容Web与原生的返回结构
        const selectedFile = result.output ? result.output[0] : result;

        // 过滤用户取消选择的情况
        if (selectedFile.type === "success" && selectedFile.mimeType === "application/pkcs12") {
            let fileObj;
            // 原生端需将uri转换为File对象(Web端直接返回File)
            if (Platform.OS !== 'web') {
                const response = await fetch(selectedFile.uri);
                const blob = await response.blob();
                fileObj = new File([blob], selectedFile.name, { type: selectedFile.mimeType });
            } else {
                fileObj = selectedFile;
            }
            setCertificateFile(fileObj);
        }
    } catch (error) {
        console.error("文件选择失败:", error);
    }
};

2. 确认原生端权限配置

移动端需要配置文件访问权限才能正常读取文件:

  • iOS:在Info.plist中添加权限描述
    <key>NSDocumentsFolderUsageDescription</key>
    <string>需要访问文件以上传数字证书</string>
    <key>NSPhotoLibraryUsageDescription</key>
    <string>需要访问相册以选择证书文件</string>
    
  • Android:在AndroidManifest.xml中添加权限
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="32" />
    

3. 修正FormData上传兼容性

原生端的File对象在FormData中需要配合正确的请求头,修改onSubmit中的请求配置:

// 上传时显式设置multipart/form-data请求头
const response = await api.post("/customer", formData, {
    headers: {
        'Content-Type': 'multipart/form-data',
    },
});

同时建议在onSubmit开头打印certificateFile,确认它是有效的File对象。

4. 处理用户取消选择的场景

当用户打开文件选择器后取消操作,getDocumentAsync会返回{ type: "cancel" },原代码未处理该情况,可能引发逻辑错误,上述修改已通过selectedFile.type === "success"过滤该场景。


内容的提问来源于stack exchange,提问作者Alfredo Augusto Petri

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 20:26:14