我有一个代理服务器,需要向外部 API 服务器发出请求,以从某些文本合成语音。 在 API 文档中有一句话告诉我:请求后我将获得带有标头的第一个响应,之后我将获得流模式二进制数据,因为响应正文中有“传输编码:分块”。
所以,我正在使用
responseType: 'stream'
来完成这个事情和这段代码
export const synthesizeVoice = async (contentType: ContentType,
dataForSynthesize: string,
format: string = 'wav16',
voice: string = 'Nec_24000') => {
const token = await authHandler.getAuthData();
const date = new Date(); const timestamp = date.getTime();
const file = fs.createWriteStream(timestamp + '.wav'); // I'm storing getted data on server, so this one needed for that
const response = await axios({
method: 'POST',
url: SAPI.SS_SYNTH,
headers: {
Authorization: 'Bearer ' + token,
'Content-Type': (contentType === 'ssml') ? 'application/ssml' : 'application/text',
},
params: {
format: format,
voice: voice,
},
data: dataForSynthesize,
responseType: 'stream',
});
// I'm writting getted data to a file
response.data.pipe(file);
// and return a path on method above in call stack to return getted binary data on front
return file.path;
};
我的主要问题是,在获得第一个响应块后(如果我没有弄错的话),我的方法返回文件的路径(此时文件不是完整的形式),并且正面不是完整的音频文件。
我如何等待获取完整的二进制数据并仅在此之后发送它们,或者也许我应该使用来自前端的流请求来按块获取数据?
另外,也许这种方法不好,我应该使用其他方法?
UPD:工作代码
axios({
// nothing to changes here, I've just hidden it to short code example
})
.then(resp => {
// Event listeners on files didn't working in my case, so
// I used it with axios response
resp.data.pipe(file);
resp.data.on('end', () => {
file.close();
res.set({
'Content-Type': 'audio/wav16',
});
const resFile = fs.createReadStream(file.path).pipe(res);
});
})
.catch(err => {
console.log(err.message)
});
您可以尝试以这种方式消费数据。
file.on('data', chunk => {
console.log(chunk.toString());
});
要在数据流结束后执行某些操作,可以使用
file.on('end', chunk => {
console.log("End");
});
结合这两者,我想您将能够等待并获得完整的文件。