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

React Native中react-native-fs报错,求Android端Midi文件保存方案

Expo环境下生成并保存MIDI文件的可行方案

一、弃用react-native-fs,改用Expo官方文件系统

Expo环境不支持直接修改AndroidManifest.xml,也不兼容裸RN的react-native-fs(你遇到的RNFSFileTypeRegular为空错误就是因为原生模块未正确链接),直接用expo-file-system更适配:

  1. 安装依赖
npx expo install expo-file-system
npm install midi-writer-js
  1. 生成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();
  1. 保存到应用私有目录(无需额外权限)
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实现:

  1. 安装依赖
npx expo install expo-media-library
  1. 保存到公共目录的代码
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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 18:52:49