求助,ctx.body在特定情况下失败
发布于 2 个月前 作者 fuxingZhang 533 次浏览 来自 问答

场景: 前端上传一个视频 ==》 服务器A(存在本地,上传到对象存储后删除) ==》 对象存储服务器 ==》 反馈前端 视频地址 故障: 1)当视频较小,在100M之下的时候是正常的,前端能正常收到消息 2)视频大于100M,服务器已经执行到ctx.body,但是前端还在一直等待,无法收到ctx.body发送的消息 伪代码:

// write to local
await wirteToLocal()

// upload
await putObject()

// send to front end
ctx.body = {
  video_id: res.fileId,
  video_url: res.video.url
}

服务器打印日志 image.png

浏览器内network信息 image.png

一直等待,实际上已经执行完毕(无法理解的是视频较小的情况下是正常的) image.png

2 回复

虽然不知道什么原因。不过你可以试试 直接 ctx.res.end()

@cd-xulei 试过了,跟ctx.body的表现一致,推测是长时间和前端没有数据交换,keepalive不再刷新时间,socket最终被销毁。

考虑 1、PassThrough定时传输没有实际意义的数据来保持连接; 2、不把文件写到服务器,直接pipe到对象存储服务器。

我最终选择的是直接pipe到对象存储服务器

PassThrough的实现逻辑(伪代码)

const PassThrough = require('stream').PassThrough;
let stream = new PassThrough();
ctx.response.status = 200;
ctx.response.type = 'text/event-stream;charset=utf-8';
ctx.response.set('Cache-Control', 'no-cache');
ctx.body = stream;
//保持连接
settimeout递归/setIntervel ==> stream.write(`working`);
//结束
clearTimeout
ctx.res.end(JSON.stringify({fileId,video_url}))
回到顶部