React Native中react-native-fs报错,求Android端Midi文件保存方案
Expo环境下生成并保存MIDI文件的可行方案
一、弃用react-native-fs,改用Expo官方文件系统
Expo环境不支持直接修改AndroidManifest.xml,也不兼容裸RN的react-native-fs(你遇到的RNFSFileTypeRegular为空错误就是因为原生模块未正确链接),直接用expo-file-system更适配:
- 安装依赖
npx expo install expo-file-system npm install midi-writer-js
- 生成MIDI数据(和PC端逻辑一致)
import MidiWriter from 'midi-writer-js'; // 生成Hot Cross Buns的MIDI轨道 const track = new MidiWriter.Track(); track.addEvent([ new MidiWriter.NoteEvent({pitch: ['C4'], duration: '4'}), new MidiWriter.NoteEvent({pitch: ['D4'], duration: '4'}), new MidiWriter.NoteEvent({pitch: ['E4'], duration: '2'}), new MidiWriter.NoteEvent({pitch: ['C4'], duration: '4'}), new MidiWriter.NoteEvent({pitch: ['D4'], duration: '4'}), new MidiWriter.NoteEvent({pitch: ['E4'], duration: '2'}), new MidiWriter.NoteEvent({pitch: ['E4'], duration: '8'}), new MidiWriter.NoteEvent({pitch: ['F4'], duration: '8'}), new MidiWriter.NoteEvent({pitch: ['E4'], duration: '8'}), new MidiWriter.NoteEvent({pitch: ['D4'], duration: '8'}), new MidiWriter.NoteEvent({pitch: ['C4'], duration: '2'}), ]); const writer = new MidiWriter.Writer([track]); // 生成base64格式的MIDI内容 const midiBase64 = writer.base64();
- 保存到应用私有目录(无需额外权限)
import * as FileSystem from 'expo-file-system'; async function saveMidi() { // 应用私有目录路径,Android上对应/data/user/0/[包名]/files/ const filePath = `${FileSystem.documentDirectory}hot-cross-buns.midi`; try { await FileSystem.writeAsStringAsync( filePath, midiBase64, { encoding: FileSystem.EncodingType.Base64 } ); alert(`MIDI已保存:${filePath}`); } catch (err) { console.error('保存失败:', err); alert('保存失败,请重试'); } }
二、保存到公共下载目录(需权限)
如果要让文件在系统文件管理器的“下载”文件夹中可见,用expo-media-library实现:
- 安装依赖
npx expo install expo-media-library
- 保存到公共目录的代码
import * as FileSystem from 'expo-file-system'; import * as MediaLibrary from 'expo-media-library'; async function saveToPublicDownload() { // 请求存储权限 const { status } = await MediaLibrary.requestPermissionsAsync(); if (status !== 'granted') { alert('需要开启存储权限才能保存到公共目录'); return; } // 先写入临时缓存目录 const tempPath = `${FileSystem.cacheDirectory}temp.midi`; await FileSystem.writeAsStringAsync(tempPath, midiBase64, { encoding: FileSystem.EncodingType.Base64 }); // 移动到系统下载目录 const asset = await MediaLibrary.createAssetAsync(tempPath); await MediaLibrary.createAlbumAsync('Download', asset, false); alert('文件已保存到系统下载目录'); }
三、别再用rn-nodeify/ReactNativify
这些工具是给裸RN项目适配Node.js环境用的,Expo本身不兼容这类修改,会触发AsyncStorage等原生模块冲突,直接用Expo官方API就能搞定,完全没必要折腾。
四、解释下之前的报错原因
你遇到的TypeError: Cannot read property 'RNFSFileTypeRegular' of null,是因为react-native-fs需要手动链接原生模块,但Expo不允许这种操作,也没有对应的config插件支持,所以直接替换成expo-file-system是最直接的解决办法。
内容的提问来源于stack exchange,提问作者elf2022
相关产品推荐
相关产品推荐

