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

Flutter http.MultipartRequest上传MIDI文件后头部异常求助

问题描述

开发项目网站时,用户通过Flutter上传MIDI文件至后端处理后返回,但上传后的文件头部出现随机字符,导致Python的mido库无法识别为有效MIDI文件。FTP上传的文件正常,Flutter上传的文件头部异常,报错提示找不到MTrk头。

同一文件FTP与Flutter上传后的头部对比:
MIDI文件头部对比

Mido报错信息

b'\xbf\xbdMT'
Traceback (most recent call last):
  File "generate.py", line 141, in <module>
    midi_file = MidiFile(MIDI_PATH)
  File "/usr/local/lib/python3.8/dist-packages/miditoolkit/midi/parser.py", line 31, in __init__
    mido_obj = mido.MidiFile(filename=filename, clip=clip, charset=charset)
  File "/usr/local/lib/python3.8/dist-packages/mido/midifiles/midifiles.py", line 324, in __init__
    self._load(file)
  File "/usr/local/lib/python3.8/dist-packages/mido/midifiles/midifiles.py", line 359, in _load
    self.tracks.append(read_track(infile,
  File "/usr/local/lib/python3.8/dist-packages/mido/midifiles/midifiles.py", line 181, in read_track
    raise IOError('no MTrk header at start of track')
OSError: no MTrk header at start of track

Flutter上传代码

void _pickFile() async {
    final result = await FilePicker.platform.pickFiles(allowMultiple: false);

    if (result == null) {
      return;
    }

    setState(() {
      _isLoading = true;
    });

    if (result.files.first.bytes != null) {
      final request =
          http.MultipartRequest('POST', Uri.parse(genAPI));
      request.files.add(await http.MultipartFile.fromBytes(
          'file', result.files.first.bytes!,
          contentType: MediaType('audio', 'midi')));
      print("files");
      print(request.files);
      try {
        final response = await request.send();
        if (response.statusCode == 200) {
          // Do something with the response
          print("response");
          print(response);
          setState(() {
            _isDownloadable = true;
            _file = result.files.first;
          });
        } else {
          // Handle error response
          print(response);
        }
      } catch (e) {
        // Handle network errors
        print(e);
      }
    } else {
      print('ERROR');
    }

    setState(() {
      _isLoading = false;
    });
  }

Node.js接收代码

app.post('/process-file', upload.single('file'), (req, res) => {
  // Check if req.file is defined
  if (!req.body.file) {
    console.log("NO FILE IN REQUEST");
    return res.status(400).send('No file uploaded');
  }

  // Get the uploaded file from the request object
  const file = req.body.file;

  const fpath = Date.now() + '.mid'; //file.originalname;

  // Write file to disk
  fs.writeFileSync('uploads/orig_' + fpath, file, (err) => {
    if (err) {
      console.error(err);
      return res.status(500).send('Error writing file to disk');
    } else {
      console.error('file loaded successfully');
    } 
  });

});

问题原因与解决方法

核心问题

问题出在Node.js后端的文件接收逻辑:使用upload.single('file')(multer中间件)后,错误地从req.body.file读取文件内容,而非req.file。req.body中的内容是经过编码的文本格式,直接写入磁盘会导致文件头部出现乱码,破坏MIDI文件的二进制结构。

修复步骤

  1. 修正Node.js后端逻辑:
    将读取文件的来源改为req.file,并使用req.file.buffer获取原始二进制数据写入磁盘。同时fs.writeFileSync是同步方法,无需传入回调函数,调整后的代码如下:

    app.post('/process-file', upload.single('file'), (req, res) => {
      // 检查是否存在上传文件
      if (!req.file) {
        console.log("NO FILE IN REQUEST");
        return res.status(400).send('No file uploaded');
      }
    
      const fpath = Date.now() + '.mid';
      const filePath = 'uploads/orig_' + fpath;
    
      try {
        // 写入原始二进制数据
        fs.writeFileSync(filePath, req.file.buffer);
        console.log('file loaded successfully');
        res.status(200).send('File uploaded and saved');
      } catch (err) {
        console.error(err);
        return res.status(500).send('Error writing file to disk');
      }
    });
    
  2. Flutter端验证:
    Flutter的http.MultipartRequest和MultipartFile.fromBytes是正确的二进制上传方式,无需修改。确保genAPI指向正确的后端接口即可。

补充说明

  • 使用multer中间件时,上传的文件信息会被解析到req.file中,包含buffer(原始二进制数据)、originalname(原文件名)等字段;req.body仅用于接收普通表单字段。
  • MIDI是二进制格式,必须保证上传、传输、存储全程使用二进制处理,任何文本编码/解码操作都会破坏文件结构。

内容的提问来源于stack exchange,提问作者Marwan Sabry

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 09:47:47