Nest 大文件上传尝试
大家圣诞节快乐呀,我是晨光,上周五看到 @神说要有光 光哥发的文章,原文见,https://articles.zsxq.com/id_4iqlbn0nqofl.html
出于好奇,跟着光哥的文章敲了一遍,自己遇到了一些困惑,并尝试解决,过程还是蛮有趣的,分享给大家
1、分片太多,合并时文件无法还原
我随手截图一张,大概有 7.2 M,上传后合并的图片,发现只有很小的一部分

我限制分片 20 次,合并后的图片如下,只有头部的一小部分,不清楚问题出在哪里,需要去定位问题。

做实验,发现 size 比较小的图片,分片的次数少,合并后没有问题,所以我尝试调整分片的次数,比如,调整为 10 次,测试后发现,合并后的图片正常了!!

2、怎么保证分片的次数是 小于等于 10 的呢?
之前分享的分段请求里面有提到过,不是无限制的分段,需设置一个边界值,也就是不让它分片的次数太多,需要在某个范围内,那应用到这里,最大分片次数为 10
根据上传的文件的大小,除以分片的 size,和 10 来比较,根据比较的结果,得到最终真实的分片的 size。

附上代码
这样做有个好处,我们无法控制上传的图片到底有多大,但是能够保证最大的分片次数是 10,那最终合并的文件就不会有问题。
3、为什么要保证分片次数 <=10 ?
查了很多资料,也有很多猜想
- 浏览器并发限制,但是请求都在本地,而且都发送成功,所以应该不是这个原因
- 在 Node.js 中,EventEmitter 是一个用于处理事件的基类。当一个 EventEmitter 实例被创建时,它会默认添加一个最大监听器数量为 10 的限制;这个原因也不太像
- 分片顺序不正确:如果分片上传的顺序不正确,合并后的文件可能会损坏。确保在合并分片之前按照正确的顺序进行合并。感觉有点像这个
说干就干, debug 了一下代码,发现读取到的文件顺序,1 后面竟然是 10,照这样合并确实会有问题。
解决办法:尝试给文件排个序,从而保证分片读取的顺序正常。

按照上面的文件名格式,我们写个排序方法把文件的顺序给调过来
我们重新上传一次,分片还是 20 ,有了排序方法,文件的读取顺序正常了,

最终合并出来的图片也正常了!!

印证了之前的猜想,确实是因为文件读取顺序导致合并异常的,再修最大批次数为 30,发现依旧可以合并正常。
4、优化文件名排序
基于上面的代码,我们给上传的文件重命名,多加个短横线,

发现上传后合并又出现了之前的问题,合并的图片又只能展示出一小部分了,推测可能是排序出了问题,排查发现,现在的文件名 932769_test2-name.png-8 有多个短横线

我们优化一下排序方法,不管名称中有多少个短横线,都只取最后一个值来进行排序
修改后,重新上传,合并后的文件也能正常展示了。至此,我的探索结束
5、总结
- 遇到问题不要退缩,大胆假设并验证
- 限制最大批次为 10 的操作看起来有点多余,不是必须的,只能算是锦上添花啦
- 分片合并的时候,文件读取顺序很重要
- 为了确保文件读取顺序,需要进行排序,因此在文件分片上传时就需要有标识位能够确保文件的顺序
以上,全文完,Nest 还挺有意思的,以后多研究研究,大家有收获点个赞呀~
