通过 ajax 上传二进制编码的音频文件并保存

Upload a binary encoded audio file via ajax and save

我有一个音频文件保存在本地,我想阅读,通过ajax上传到服务器,然后存储在服务器上。在此过程中的某个地方,文件已损坏,无法播放保存在服务器上的文件。

我将列出一些简化的代码,这些代码显示了我正在经历的过程,因此希望它会很明显地指出我哪里出错了。

1) 录音后(使用getUserMedia and MediaRecorder),保存到本地文件:

var audioData = new Blob(chunks, { type: 'audio/webm' });
var fileReader = new FileReader();
fileReader.onloadend = function() {
    var buffer = this.result,
        uint8Array = new Uint8Array(buffer);

    fs.writeFile('path/to/file.webm', uint8Array, { flags: 'w' });
}
fileReader.readAsArrayBuffer(audioData);

2) 稍后读取此本地文件并发送到服务器(使用库 axios 发送 ajax 请求)

fs.readFile('path/to/file.webm', 'binary', (err, data) => {
    var formData = new FormData();
    formData.append('file', new Blob([data], {type: 'audio/webm'}), 'file.webm');
    axios.put('/upload', formData);
});

3)服务器然后处理这个请求并保存文件

[HttpPut]
public IActionResult Upload(IFormFile file)
{
    using (var fileStream = new FileStream("path/to/file.webm", FileMode.Create))
    {
        file.CopyTo(fileStream);
    }
}

本地音频文件可以播放成功,但是服务器上的音频文件无法播放

我不确定这是否有用的信息,但这是我在文本编辑器 (notepad++) 中打开本地文件时看到的前几行文本:

当我在服务器上打开时也是如此:

有点相同...但不同。我尝试了无数种不同的编码方式,但一切似乎都失败了。祈祷有人能在这里为我指明正确的方向。

问题在于我如何传递来自 fs.readFile 的文件内容。如果我通过 json 从 fs.readFile 传递一个 base64 编码的原始缓冲区,将其转换为服务器上的字节数组并保存,那么我就可以在服务器上成功播放它。


fs.readFile('path/to/file.webm', (err, data) => {
    axios.put('/upload', { audioData: data.toString('base64') });
});

[HttpPut]
public IActionResult Upload([FromBody]UploadViewModel upload)
{
    var audioDataBytes = Convert.FromBase64String(upload.AudioData);

    using (var memoryStream = new MemoryStream(audioDataBytes))
    using (var fileStream = new FileStream("path/to/file.webm", FileMode.Create))
    {
        await memoryStream.CopyToAsync(fileStream);
    }
}

其实这是字符编码的问题。您可能混合了 UTF-8 和 ISO-8859,这会导致文件损坏。

您应该将 HTML 页面中的字符集设置为服务器上预期的字符集。或者如果您不知道您将收到的数据的字符集,请在服务器上执行初步检查。

转换为 base64 将解决问题,因为那样它只会使用 ASCII 范围内的字符。