赞
踩
正常的向后端发送请求,常见的 get、post 大家都很熟悉,是没有任何问题的;我们也可以用 post 或者表单请求发送 file文件 到后端。 但是大文件的上传是一个特殊的情况: 大文件上传最主要的问题就在于:在一个请求中,要上传大量的数据,导致整个过程会比较漫长,且失败后需要重头开始上传。
首先是上传过程时间比较久(要传输更多的报文,丢包重传的概率也更大),在这个过程中不能做其他操作,用户不能刷新页面,只能耐心等待请求完成。
常见的软件应用中,前端/后端都会对一个请求的时间进行限制,那么大文件的上传就会很容易超时,导致上传失败。
如何上传大文件呢
1.文件切片
在 JavaScript
中,文件 File
对象是 Blob
对象的子类,Blob
对象包含一个重要的方法 slice
,通过这个方法,我们就可以对二进制文件进行拆分。
将文件拆分成 size
大小(可以是100k、500k、1M…)的分块,得到一个 file
的数组 fileChunkList
,然后每次请求只需要上传这一个部分的分块即可。服务器接收到这些切片后,再将他们拼接起来就可以了。
2.得到原文件的hash值
拿到原文件的 hash
值是关键的一步,同一个文件就算改文件名,hash
值也不会变,就可以避免文件改名后重复上传的问题。
我们可以使用 spark-md5.min.js 来根据文件的二进制内容计算文件的 hash。
说明:考虑到如果上传一个超大文件,读取文件内容计算 hash 是非常耗费时间的,并且会引起 UI 的阻塞,导致页面假死状态,所以我们使用 web-worker 在 worker 线程计算 hash,这样用户仍可以在主界面正常的交互。
由于实例化 web-worker 时,参数是一个 js 文件路径且不能跨域,所以我们单独创建一个 hash.js 文件放在 public 目录下,另外在 worker 中也是不允许访问 dom 的,但它提供了importScripts 函数用于导入外部脚本,通过它导入 spark-md5。
3.文件上传
1)验证文件是否已经在服务端存在,如果存在,那就不用上传了,相当于秒传成功。
如果 shouldUpload
为 false
,则表明这个文件不需要上传,提示:秒传成功。
2)然后上传除了 uploadedList
之外的文件切片。
4.文件合并
1、前端发送切片完成后,发送一个合并请求,后端收到请求后,将之前上传的切片文件合并。
2、后台记录切片文件上传数据,当后台检测到切片上传完成后,自动完成合并。
3、创建一个和源文件大小相同的文件,根据切片文件的起止位置直接将切片写入对应位置。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。