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

React Native Expo构建后无法读取assets目录CSV文件求解决方案

问题描述

开发的React Native Expo应用用于读取CSV数据,使用FileSystem和Expo Asset访问文件。开发阶段在Google Project IDX编写代码,Web版本调试及执行expo start时均正常,CSV文件可正常读取;但通过EAS构建应用后,CSV文件无法被找到,界面始终显示“Loading...”。

CSV文件位于Expo的assets目录(assets/jadwal_sholat.csv),index.tsx在app目录下。已尝试USB调试,但log.txt中无报错信息,直接使用require()路径也无效。

相关代码:

类型定义与数据加载逻辑

interface ParsedSholatTimes {
    Tanggal: string;
    Subuh: string;
    Dzuhur: string;
    Ashar: string;
    Maghrib: string;
    Isya: string;
}

useEffect(() => {
    const fetchCsvData = async () => {
        try {
            const asset: Asset = Asset.fromModule(require('../assets/jadwal_sholat.csv'));
            await asset.downloadAsync();
            const csvFile: string = await FileSystem.readAsStringAsync(asset.localUri || '');

            Papa.parse<ParsedSholatTimes>(csvFile, {
                header: true,
                complete: (results: ParseResult<ParsedSholatTimes>) => {
                    const now = new Date();
                    const formattedToday = `${now.getDate()}/${now.getMonth() + 1}/${now.getFullYear()}`;

                    const todayTimes = results.data.find((row: ParsedSholatTimes) => {
                        const [day, month, year] = row.Tanggal.split('/').map(Number);
                        const csvDate = new Date(year, month - 1, day);

                        return (
                            csvDate.getDate() === now.getDate() &&
                            csvDate.getMonth() === now.getMonth() &&
                            csvDate.getFullYear() === now.getFullYear()
                        );
                    });

                    if (todayTimes) {
                        setSholatTimes(todayTimes);
                    } else {
                        console.log('No times found for today');
                    }
                },
            });
        } catch (error) {
            console.error('Error fetching or parsing CSV:', error);
        }
    };

界面渲染代码

{prayerTimes.map((prayer: PrayerTime, index: number) => {
    const borderColor = tw`border-${prayer.color}`;
    const bgColor = tw`bg-${prayer.color}`;
    return (
        <View key={prayer.name} style={[tw`w-full bg-neutral-100 p-3 rounded-xl mb-3`, borderColor]}>
            <View style={tw`flex-row items-center justify-between`}>
                <View style={tw`flex-row items-center`}>
                    <View style={[tw`rounded-full px-5 py-3 mr-2 w-44 `, bgColor]}>
                        <Text style={tw`text-3xl font-bold text-white text-center`}>{prayer.name}</Text>
                    </View>
                </View>
                <Text style={tw`text-4xl font-bold`}>{prayer.time || 'Loading...'}</Text>
            </View>
        </View>
    );
})}
解决方案

1. 确保assets在app.json中正确声明

Expo EAS构建时,只有在app.json的expo.assets数组中声明的资源才会被打包进应用。打开app.json,检查是否包含以下配置:

{
  "expo": {
    "assets": [
      "./assets/**/*" // 匹配所有assets目录下的文件
      // 或者精确指定 "./assets/jadwal_sholat.csv"
    ]
  }
}

2. 调整CSV文件加载逻辑(适配EAS构建环境)

EAS构建后,打包的资源路径与开发环境不同,无需调用downloadAsync,直接通过FileSystem.bundledAssets访问打包后的文件:

useEffect(() => {
    const fetchCsvData = async () => {
        try {
            // 直接访问打包后的CSV文件路径
            const csvPath = `${FileSystem.bundledAssets}/jadwal_sholat.csv`;
            // 先验证文件是否存在
            const fileInfo = await FileSystem.getInfoAsync(csvPath);
            if (!fileInfo.exists) {
                console.error('CSV文件不存在:', csvPath);
                return;
            }
            const csvFile = await FileSystem.readAsStringAsync(csvPath);

            Papa.parse<ParsedSholatTimes>(csvFile, {
                header: true,
                complete: (results) => {
                    const now = new Date();
                    const todayTimes = results.data.find((row) => {
                        const [day, month, year] = row.Tanggal.split('/').map(Number);
                        const csvDate = new Date(year, month - 1, day);
                        return (
                            csvDate.getDate() === now.getDate() &&
                            csvDate.getMonth() === now.getMonth() &&
                            csvDate.getFullYear() === now.getFullYear()
                        );
                    });

                    if (todayTimes) {
                        setSholatTimes(todayTimes);
                    } else {
                        console.log('今日无祈祷时间数据');
                    }
                },
                error: (error) => {
                    console.error('CSV解析错误:', error);
                }
            });
        } catch (error) {
            console.error('加载CSV失败:', JSON.stringify(error));
            // 可添加Alert提示用户
            // Alert.alert('加载失败', '无法读取祈祷时间数据');
        }
    };

    fetchCsvData();
}, []);

3. 增强错误日志排查

USB调试的log.txt可能未捕获全部日志,建议:

  • 使用expo logs:device命令实时查看设备日志,获取更详细的错误信息
  • 在catch块中打印完整错误对象(用JSON.stringify),避免只打印错误消息丢失关键信息

4. 验证文件路径与大小写

  • 确认CSV文件名拼写完全一致(iOS系统区分文件名大小写,比如Jadwal_Sholat.csv和jadwal_sholat.csv会被视为不同文件)
  • 检查index.tsx所在目录与assets目录的相对路径是否正确(app目录下的index.tsx,相对路径../assets/jadwal_sholat.csv是正确的)

内容的提问来源于stack exchange,提问作者Sultan Zaki

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 20:33:14