普通的文件上传已经满足不了我们了,在数据量特别大的时候如传了一个4k的视屏什么的这个文件的体系显然意见的就已经很大了,而且是一个文件,再想想如果有两个或者两个以上的文件同时上传的前提下我们怎么才能保证文件上传的速度变快???只能采取分片式文件上传
分片式文件上传的好处?
大大的提升了文件上传的速度,提高了体验,减短了不必要浪费的时间
分片式文件上传坏处?
如果在某一个环节出错了就会造成堵塞,程序假死,不能正常运行
前端:vue3.0 +Ant design
使用 Ant design 官网 的一个Upload 上传组件 在 定义一个 beforeUpload函数和 handleChange change事件在beforeUpload函数中返回false,设置为手动上传的方式
然后在handleChange 事件里设定一下文件分片的操作,以文件为单位肯定要在事件中传递一个文件file 定义一个临时变量size记录文件大小 file_name记录文件名字 ,但是文件的切片并不是每一个文件都是需要去做切片的,只有在一些特殊的文件中做切片才会有具体的效果,文件的切片自始至终都是为了能更快的上传文件,如果一些文件的体积本身就不算太大,再去切片大大的浪费时间还不如直接传递给后端,所以在分片的时候我做了一个判断语句,目的就是为了控制哪些文件需要被切片哪些文件不需要做切片
文件的大小是以byte字节为单位1kb =1024字节 1mb = 104876 = 1024kb * 1024kb 限制上传大小为1mb
接下来就可以定义切片的大小,切片的大小是用来判断这个文件可以分割成多少份,用来计算文件切片的个数,(1mb)
然后就是拿着当前文件的大小除以切片文件的大小向上取整,向上取整就是为了保证文件整体,假如不能被整除剩下一点文件实体不可能不要也要发送给后端,
这样就能拿到分片的总数,然后开始将分了片的文件发送给后端
使用循环可以保证文件全部都发送给后端,如何发送?这就要涉及到文件从那个位置开始发送,从那个位置结束,类似于python中的切片从哪儿开始切到哪儿结束
然后就要对这个数据进行一次循环,以总片数作为终,保证一片都不能少,一片也不能漏,然后计算出每一次上传的起始位置跟结束为止为了发文件,文件切片的开始为止通过微微计算可以知道每一次都是切片结束的为止,切片结束的为止而是开始位置加上切片的大小那每一次切片的开始位置是多少呢?通过循环可以知道第一次开始的位置是0 第二次是 104876 第三次是 209752 每一次可以看成 每次循环乘以切片的文件大小可以轻易的得出这种有规律的大小而结束位置可以看成循环的(i+1)*104876 但是要担忧一件事情什么事儿呢就是如果当分片之后最后一次分片的大小到底是多少呢?所以使用min取一个最小值,不是最后一片的时候什么取都是在文件大小内的直到最后一次才能算是正式的比对去掉了弊端
然后就是对文件对应的切片发送了!文件切片的话有一个内置的方法 slice 类似于python中的[:]切片最后写一个请求将前端的数据传递给后端,让后端进行进一步的操作
这就是文件大于设定的文件时候切片上传的逻辑而没有到切片限制去哪儿了?不要担心,不需要切片的文件也是上传到后端了调用的也是同一个接口同一个请求
这个接口就是真正的向后端发送上传文件的请求,只需要在这个事件中添加一个新的表单,用来给后端接受数据,后端什么类型的数据可以自己定义,拿去自己所需要的就行
再声明一下文件的配置
这样就离成功不远了加油!!
向后端发送一个post请求,把表单里面的数据发给后端,后端接受前端传送过来的切片后的文件
到这前端算是完成了发送切片后的数据的任务接下来就是后端存储这些切片什么的
使用tornado采用异步的形式完成图片的接受,都说屎使用tornado异步了那肯定少不了async和await关键字,这两个关键字是开启tornado异步的关键呐!
接受前端传递过来的参数
(我在BaseManage中做了封装用来封装一些常用的方法等,这里就不细说了简单带过一下)
直接调用父类中的io_file方法向这个方法中传递我们操作文件等需要的关键字
实例化IOS_FILes在这个方法中有初始化方法 __init__ 须要传递这些特定的参数,方便操作
然后在异步调用里面的post_file()用来完成分片文件上传来看看都实现了什么?
__path是这个类里面的私有变量 (感兴趣的可以去搜索一下)
然后在创建一个pos_file的方法采用了 aiofiles 一个异步操作文件的插件,提高文件写入效率
异步操作的时候千万不要忘记async和with关键字!