通过 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 范围内的字符。
我有一个音频文件保存在本地,我想阅读,通过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 范围内的字符。