面试题:前端文件上传
一:基本回答
前端使用type为file的input的,以及formData,将文件通过ajax传给后端。
二:进阶之文件切片
将文件分为若干个小块,然后依次上传,后端接受完所有文件后再合并。
相较于上面的优点是可以断点续传和秒传,切片后每个小块通过md5计算其唯一的hash值,上传时都问后端校验下,是否存在该块,不存在才上传,如果整个文件都存在的话那就是秒传了。
三:进阶之优化计算hash
切片后每个小块计算hash较耗费时间,此时页面就会卡住,影响用户体验,解决方法有:
- webworker,开一个子进程去计算hash,主线程只需要等待其完成的通知即可,计算量没有减少,但主线程不卡顿;优点是逻辑简单,缺点是增加了网络请求;
- time-slice,时间切片,利用浏览器空闲时间去计算hash,不影响延迟浏览器的关键事件,如动画和输入响应等,原理是浏览器的requestIdleCallback方法;优点是效率比webworker的高,更细腻,缺点是requestIdlecallback该api有兼容问题,自己实现较为复杂,可参考react的fiber架构 ;
- 抽样hash,也就是不把小块的全部文件去做全量hash,而是抽取其前中后两个字节,共6个字节去计算hash(大概思路,细节还要更复杂);牺牲一些命中率,换取时间;可以结合上面两种方法使用;
三:进阶之优化大量请求
切片后增加了上传文件的请求数量,需要控制请求的并发数以及失败重试;
至于判断每个小块是否存在的请求,可以只需要一个,后端返回已经存在的文件hash的数组,之后的判断无需一个个请求;
四:进阶之慢启动策略
解决的是分片到底分多大的问题,不能写死为1m或是200kb,需要根据当前网络情况,动态调整切片大小数,参考TCP的慢启动策略;
具体为,假设理想是每30s上传一个区块,区块初始大小为1m,如果上传只用了10s,则下一个区块大小为3m;如果花了60s,则下一个区块变成500kb;以此类推,由于网速波动,区块大小需要一直判断;
更多优化点
- 碎片清理,定期清理服务器过期的碎片文件
- requestIdleCallback兼容性,如何自己实现一个
- 并发+慢启动配合
- 抽样hash+全量量哈希+时间切片配合
- 慢启动的变化应该更更平滑,比如使用三⻆角函数,把变化率平滑的限制在0.5~1.5之间
- websocket推送进度
- 文件碎片分机器器存储
- 文件碎片备份
- 体验优化,如上传的进度条、离开页面的提醒、拖拽上传、粘贴上传等
......
【自己的感悟之 学习的慢启动】
从小的任务开始,能够顺利地完成,再加大任务,不要一开始就搞个大的任务,高的期望反而卡住了,那就一点都没有完成。
后续还需要自己用代码全部实践一遍,以及运用的项目中
整理于 开课吧-大圣老师的2020.2.7号直播
ps:晚上看到煎蛋站长 染新冠肺炎发文交代后事--诸君,我可能感染了新冠肺炎 ,后检查发现不是,替他感到高兴,白嫖党第一次打赏十块,有5000+的人打赏,如此近距离的直面死亡,又回到人间,会有一些什么样的感悟呢?
网友评论