如何手写一款KOA的中间件来实现断点续传

如何手写一款KOA的中间件来实现断点续传

本文实现的断点续传只是我对断点续传的一个理解。其中有很多不完善的地方,仅仅是记录了一个我对断点续传一个实现过程。大家应该也会发现我用的都是一些H5的api,老得浏览器不会支持,以及我并未将跨域考虑入内,还有一些可能出现的一场等~巴啦啦。(怎么感觉这么多问题???笑~)

本文参考仓库:点我

这几天在认认真真地学习KOA框架,了解它的原理以及KOA中间件的实现方法。在研究KOA如何处理上传的表单数据的时候,我灵光一闪,这是不是可以用于断点续传?

断点续传并不是服务器端一端的自high,他还需要前端的配合,而且我只准备扒拉一个大致的雏形,所以这个功能我准备:

后端:手写KOA中间件处理断点数据

前端:原生JS

断点续传的过程不复杂,但是还是有许多小知识点需要get,不然很难理解断点续传的工作过程。实现断点续传的方式有很多,不过我只研究了ajax的方式,所以预备的小知识点如下:

KOA部分: Headers的content-type Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryE1FeIoZcbW92IXSd

HTML的form组件一共提供三种方式的编码方法:application/x-www-form-urlencoded(默认)、multipart/form-data、text/plain。前两种方式比较常见,最后一种不太用,也不推荐使用。前两种的区别就是默认的方法是无法上传<input type="file"/>的。所以如果我们需要上传文件,那么就一定要用multipart/form-data。

form上传的raw data

在KOA中,server获取到的data都是raw data也就是未经处理的二进制数据。我们需要格式化这些数据,提取有效内容。我们来分析一下如何处理这些raw data。

当我们上传的时候,我们会发现一个现象,就是content-type还跟了一个小尾巴multipart/form-data; boundary=----WebKitFormBoundarygNnYG0jyz7vh9bjm,这个长串的字符串是用来干嘛的呢?看一眼完整的raw data :

------WebKitFormBoundarygNnYG0jyz7vh9bjm Content-Disposition: form-data; 668 ------WebKitFormBoundarygNnYG0jyz7vh9bjm Content-Disposition: form-data;; filename="checked.png" Content-Type: image/png ------WebKitFormBoundarygNnYG0jyz7vh9bjm--

大家发现没每个字段之间都有------WebKitFormBoundarygNnYG0jyz7vh9bjm将他们分割开来。所以这里的boundary是用来分割字段的。

关于boundary

它的值是可以自定义的,不过浏览器会帮我们定义

不能超过70个字符

在raw data中,需要在前方加上--,也就是这样--boundary,如果是结尾的分隔符那么在末尾也加一个--,就是这样--boundary--

更多详情,请参考The Multipart Content-Type

http中request的data和end监听事件

传数据给server,他也要有办法接受对不?所以这个时候,我们需要配置data监听数据的接受,以及end监听数据的接受完毕。

每次data事件触发,获取的数据都是一个Buffer类型的数据,然后将获取到的数据加到buf数组中,等结束的时候,再用Buffer.concat串联这些Buffer数据,变成一个完整的Buffer。就是这样,服务器将客户端的数据接受完毕了。

这一段就很简单了,ctx.req是KOA中封装的request。

let buf = []; let allData; ctx.req.on("data",(data)=>{ buf.push(data) }); ctx.req.on("end",(data)=>{ allData=Buffer.concat(buf) }) Buffer的处理

重点部分来了,这一部分了坑得我好惨。

我们server获取到的raw data不是字符串,而是一串Buffer。Buffer是什么呢?是二进制数据。虽然我们可以将Buffer转为字符串再进行处理,但是遇到编码问题就会很头疼,因为toString默认是utf-8得编码格式。如果遇上不是utf-8的,那么我们得到的结果就很有问题。所以说如果想要加工Buffer数据就还是要用Buffer数据。比如------WebKitFormBoundarygNnYG0jyz7vh9bjm这一段我想知道再Buffer中这个一段的位置。那么我么可以把这一段变成Buffer,然后去逐个查询。

来一段我和raw data的血泪沟通史(P一下哈哈):

raw data 我
我是一段二进制流   我要处理你  
  我要把你变成我最爱的string,人类可读的语言,然后再分割你  
如果我本来是人类可读,那么你可以这么做,万一我是图片或者其他格式,emmm   会有什么问题吗  
那么你就看不到我原来的样子了   ???  
简而言之,如果我是图片,你把我转成文字,写入文件的话,我就是一堆乱码   what???(Φ皿Φ)  
所以你只能用我的同类来处理我   同类?  
也就是二进制流   也就是说我要把分隔符变成二进制流,然后来分割你?  
就是这样~   大哥我输了  
虽说我是二进制流,不过你可以用一个熟悉的方法来查询我   咦?有捷径吗?  
可以帮助你查询位置    
可以帮助你无损分割我    
我只能帮你到这儿了   走好,不送  

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpdsyz.html