服务器返回时无法解码音频文件

Can't decode audio file when returned by server

在服务器(节点 + koa.js)上,这是我获取文件并设置响应的 body 的方式:

fs.readFile(file.wav, (err, data) => {
    ctx.body = data; // data is a Buffer
});

请求文件时,服务器returns响应如下headers:

HTTP/1.1 200 OK
Access-Control-Allow-Origin: *
Content-Type: application/octet-stream
Content-Length: 49396932
Date: Sat, 09 Sep 2017 14:55:35 GMT
Connection: keep-alive

到目前为止一切顺利。前端出现问题。

this.filesService.readContent().subscribe(response => {
    let arrayBuffer = response.arrayBuffer();

    console.log(response._body) //"RIFF���WAVEfmt D��data0������[...]d3 *ID3 TXXXSoftwareFL Studio 11"
    console.log(response._body.length) //47616738
    console.log(arrayBuffer.byteLength) //95233476

    audioContext.decodeAudioData(arrayBuffer).catch(e => {
       console.log(e) //DOMException: Unable to decode audio data
    })
});

为什么我不能解码这个音频文件?

此外,我想知道:

  1. 为什么 body 的响应如此容易阅读?例如,"ID3 TXXXSoftwareFL Studio 11" 看起来像是普通文本,而不是字节。是不是编码问题?
  2. 为什么 body 长度是 47616738 而不是 49396932 (Content-Length header)
  3. 为什么数组缓冲区有双倍大小?

我知道我的文件是一个完全有效的文件,并且可以从浏览器中解码。如果我手动获取与服务器 returns 相同的文件并使用输入文件将其上传到我的应用程序,浏览器对其进行解码没有问题。

问题要么是服务器 returns 文件的方式,要么是 angular 2 解释响应的方式。

感谢任何帮助:)。干杯!

当调用 response.arrayBuffer() 时,angular 将正文转换为具有 Uint16Array 视图的 ArrayBuffer,我认为这解释了为什么 response.arrayBuffer().byteLength 有两倍大小.

但是,如果您事先告诉 angular 您期望的响应内容类型是 ArrayBuffer,关联的视图将是 Uint8Array:

readContent() {
    return this.http.get(url, { responseType: ResponseContentType.ArrayBuffer })
}

似乎 decodeAudioData 只适用于 Uint8Array