项目中有使用一个gridfs的库,利用Mongodb的GridFS实现文件存储和分片读取数据。但是组员出现了音频总是丢几秒的问题,还有视频也是。
后来我发现是duration为无穷大,于是找了点办法,例如设置currentTime特别大让组员试试。他弄了几天发消息让我再看看,刚好有点空,也就试了试。
过程和思路如下:(环境是Meteor后端,ufs作为前后端的上传和下载)
-
拦截请求的处理函数,由于注意到请求一直pending, 怀疑是没有关闭socket导致的无限加载,于是想要在数据流关闭后结束请求。 ---看了看源码,突然意识到koa的好处,请求返回都可处理,但是目前这个框架用的类express的插件,然后res被拦截了,插件配置又只能读取到请求,没法在它干完活儿之后主动关闭,我就不得不把respone 关联到了request对象,试了关闭之后,还是有问题。
-
分析请求头,发现有几个请求很奇怪,Range=11333-11333/11334 类似这样。于是我以为是因为这个起始值一样导致的,于是在发现起始和结束值相同的时候,就从写range,还看到了Range=11333- 这样的情况,于是就返回416。但是发现依旧无法解决,于是开始看源码了啦;
-
源码有解析Content-Range,或者做比较什么的,保证不超过文件大小,然后获得起始值之后从数据库拿数据,看上去没什么问题。然后我就看getDownloadStream的参数,发现了比较奇怪的地方。 range的值似乎是包含结尾的,看了MDN 也确实 end和start都是inclusive的- Mongodb的值是类似于javascript的,end是不包含的 于是尝试重写方法,毕竟JS很灵活 类似于:
const oldFun = obj.a
obj.a = function(a1,a2){
if(a2.end){
a2.end +=1;
}
return oldFun(a1,a2)
}
然后我又删了之前的forK再fork再提了个PR,这次就三行代码,不知道Owner这次会不会再次close我的PR呢,上次说是我的太麻烦,哈哈。
后记,这个时候,我突然意识到了Koa设计的好处,一个插件可以处理两次请求和返回值,也就是它至少在调试的时候可以看看返回情况。 然后就是HTTP协议的认知,尤其是请求头的参数含义等等,也是该多熟悉和理解,