文件上传之切片

       今天主要讲讲文件切片,主要在上传大文件的时候需要用到,你想想,上传一个几百兆的大视频,但网络带宽又特别感人,一个不小心就报错造成上传失败,那是什么感受...

       进入正题,选择文件后,点击“确定”,首先计算出文件总大小,然后需要做什么呢,你需要告诉服务器这个大文件被切成了多少片,还得在每次上传的时候告诉它当前是第几片。最好加一个Date.now(),不然大家同时上传一个1.jpg,一到服务器就重名了,加了Date.now(),1_(时间戳).jpg就不会重名了。

       每次上传的Blob对象使用file.slice(start, end)完成:


注意红框标注的地方,每次上传都需要执行formData['delete'](fileName),至于原因已经在里面加入了,自己看哈。

下面是上传进度和上传速度的代码:

var xhr = ZUtil.getXHR(),
formData = new FormData(),
// 上次的时间戳
prev = new Date().getTime(),
// 以上传
load = 0,
// 文件大小
size = file.size,
translateSize = ZUtil.translateByte(size),
prevProgress = 0,
$bar = $row.find('.z-progress-bar'),
$progress = $row.find('.z-upload-progress'),
$speed = $row.find('.z-upload-speed'),
$progressLinear = $row.find('.z-upload-progress-linear');
formData.append('uniqueFlag', Date.now());
formData.append('fileName', file.name);
xhr.addEventListener('error', uploadError, false);
xhr.upload.addEventListener('progress', function(e) {
// e.loaded是本次请求已经上传的文件大小
var loaded,
// 当前时间戳
now = new Date().getTime(),
distance = now - prev;
if (splitUpload) {
/**
* 如果是分片上传,e.loaded是每次的file.slice(start, end),理论上就是每份文件切片大小
* 而不会像整体文件上传一样,e.loaded是从0慢慢增长到file.size
* 需要加上load才是已经上传的文件大小
*/
loaded = e.loaded + load;
} else {
loaded = e.loaded;
}
var progress = Math.min(Math.round(loaded / size * 100), 100);
/**
* 每次更新的时间间隔 >= speedUpdateInterval
* 或者上传完毕(如果是分片上传,那么e.loaded >= splitSize也意味着当前分片文件上传完成)
*/
if(distance >= speedUpdateInterval || (progress == 100 || (splitUpload && e.loaded >= splitSize))) {
var speed = ZUtil.translateByte((loaded - load) / distance * 1000);
$speed.html('速度:' + speed + '/s');
prev = now;
load = loaded;
}
if(progress != prevProgress) {
prevProgress = progress;
$progress.html('进度:' + progress + '% of ' + translateSize);
$progressLinear.css({
width : progress + '%'
});
}

下面是文件上传效果:

第一个切片:


最后一个切片:


大家也看到了,文件只有216KB,我设置的切片大小只有0.01MB,所以才会上传22次。


        onreadystatechange代码


       可以看到,每次需要后端返回success,并且当前切片index < 总切片数totalIndex才会继续上传,如果全部上传完毕,会调用afterUpload回调方法

后端java代码


       通过对比index和totalIndex,如果相同,就合并文件

       上一篇已经提过如果不适用切片,仅仅一个进度条,这都是骗人的。使用切片后,分片上传文件,等到上一片文件上传成功后才会继续上传下一片,因为公司没有要求使用数据库记录切片信息,所以每次上传切片后没有将切片文件信息保存到数据库,要是哪个切片上传失败了,只能重新上传...这样做虽然花费的时间长了一点(当然了,这么多次请求,HTTP握手肯定很费时间的),不过这样也是值得的,几百兆的大文件重复上传更费时间呢,反正还是需要开发者自己权衡,个人建议,几兆的小文件就别用切片了,麻烦。

  • 1
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
文件上传切片上传是将文件切成多个小块,然后分别上传这些小块,最后再将这些小块合并成完整的文件的一种上传方式。这种方式相对于一次性上传整个文件,可以大大提高上传的效率,尤其是对于大文件的上传,切片上传可以更好地避免因为网络不稳定等原因导致的上传失败。 下面以一个简单的示例来解释文件上传切片上传。假设我们要上传一个大小为 10MB 的文件,我们可以将它切成 10 个大小为 1MB 的小块。 1. 客户端将文件切成多个小块(如 1MB 大小的小块)。 2. 客户端依次上传每个小块,上传时可以使用 XMLHttpRequest 对象或者 Fetch API 来发送 HTTP 请求。对于每个小块的上传,客户端需要指定上传的起始位置和结束位置。 3. 服务器接收到每个小块的上传请求后,将它们存储到暂存区(如 Redis)中,等待最后的合并。 4. 客户端上传完所有小块后,发送合并请求到服务器,请求服务器将存储在暂存区中的小块合并成完整的文件。服务器读取暂存区中的小块,并将它们合并成完整的文件。 5. 服务器将合并后的文件存储到永久存储区(如硬盘)中,上传完成。 需要注意的是,如果上传过程中出现了中断或者失败,客户端可以重新上传失败或者中断的小块,而不用重新上传整个文件。同时,服务器也需要实现上传的断点续传功能,以便客户端能够在中断或者失败后继续上传。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值