android七牛断点续传,七牛图片断点续传

难点分析

七牛难道没有官方接口文档吗?还要我在这里写?有肯定是有的,地址: 七牛断点续传文档。我之所以写这篇文章,是因为它的文档比较坑,没有具体的demo,而且上传的类型也不是我们平常用到的,导致我们总是上传不成功。

根据文档我们知道,七牛的做法是将大文件分成块(block)和片(chunk)来上传的,大致如下:

aa3dba21f5c84f0cb94645364686fe91.png

为什么要这么分呢?因为块和片是有不同属性的,块是可以同时上传的,但是一个块中的片是必须一个接着一个上传,等所有的块完毕,就可以创建文件了。

当然,我们根据文档自己大致划分了块和片如下:

13opcmbgtj7_1.svg

因为官方的说法是每个block大小为4MB,最后一个不大于4MB,因此我们将一个4MB的block分成4分,每份为1MB,也就是一个chunk为1MB,注意一个block中的所有chunk之和必须等于block,而且标准的block大小就是4MB,如果你想设置3MB或者5MB必须要去修改后端的配置,如果只是前端修改这个尺寸的话,在合并所有块的时候会报错。

我们第一步是要创建一个块,创建块的时候要注意Content-Type:application/octet-stream,我们要利用ajax上传一个二进制流,注意这里用原生的ajax,关键代码如下:

if(window.XMLHttpRequest) { // code for IE7+, Firefox, Chrome, Opera, Safari

var xhr = new XMLHttpRequest();

} else { // code for IE6, IE5

var xhr = new ActiveXObject("Microsoft.XMLHTTP");

}

xhr.open("POST", 'http://up.qiniu.com/mkblk/' + size, true);

xhr.setRequestHeader('Authorization', token);

xhr.setRequestHeader('Content-Type', 'application/octet-stream');

xhr.onreadystatechange =function(){};

xhr.send(data);创建块的时候有几个参数:第一,这个块有多大,例如一个5MB的图片,需要创建两个块,一个为4MB,一个为1MB;第二,第一个片的内容,这里需要注意上传的是二进制流,我们选择的文件属于file blob,需要先用readAsArrayBuffer将blob变成二进制流;第三,需要一个Authorization,注意,这玩意不等于七牛的token,关系为Authorization='UpToken '+token。

创建完之后,会返回一个ctx和offset,当你创建下一个片的时候,需要带上上一个片的ctx和offset。

当创建完所有的片之后,就要通过mkfile接口将他们组装起来,文档上写的时候每个块最后一个片的ctx,这里注意,一定要按照块的顺序组装,否则报错,还要注意,这里的content-type为text/plain,这玩意不需要带key,直接将所有的ctx组装(用逗号分割)上传就好了。断点续传

上面讲了如何做七牛的分片上传,断点续传这里主要体现在暂停/开启和刷新页面上。

当你点击暂停之后,会将当前正在发送的请求abort,取消请求,同时保存被取消的ajax以便恢复,关键代码如下:

//记录被取消的xhr

$el.data('callback', ADAPTER.createBlock.bind(this, size, token, dis, data, $el, successBack, errorBack));

$el.data('xhr', xhr);

//取消xhr

xhr.abort();

//恢复被取消的xhr

$el.data('callback')();

刷新页面的断点续传主要是根据file.name来在cookie中生成一条记录,这个里面记录了片的ctx和offset,关键代码如下:

var cookie_data = JSON.parse(common.get_cookie(md5(file.name)));

if(cookie_data[_md5]) { //存在这个片

var $el = $html.find('.pic_unit_chunk').eq(0);

$el.attr('state', 'finish');

$el.show();

$el.find('.pic_unit_inner_chunk').addClass('select').width(100 * ((end - start)/ (1024 * 1024)) + '%');

callback(cookie_data[_md5].ctx, cookie_data[_md5].offset, $html);

} else {

ADAPTER.createBlock(size, 'UpToken ' + GLOBAL_QINIU_TOKEN, end - start, arrayBuffer, $html.find('.pic_unit_chunk').eq(0), function(data) {

var cookie_data = JSON.parse(common.get_cookie(md5(file.name)));

cookie_data[_md5] = {

ctx: data.ctx,

offset: data.offset

};

common.set_cookie(md5(file.name), JSON.stringify(cookie_data));

callback(data.ctx, data.offset, $html)

});

}当你在下次准备上传片或者块的时候看看有没有存在的,如果有,那么直接用cookie中的,如果没有,则请求。

这里要注意,刷新页面的断点续传操作是:第一次你选了a.jpg,然后上传一半的时候刷新页面,这个时候再选a.jpg才会出现刷新的断点续传,因为我们是不能直接把图片放入缓存的,缓存的空间也就几MB而已,而一张图片可能有几十MB,因此不能直接将图片存入缓存,而只能再第二次选择相同图片时触发。最后

看文章好像说的很简单的样子,真的只有等你自己写的时候才知道什么叫绝望了,报了无数个错,没有可参考的文章,只能自己去猜哪个地方可能有问题,哎,希望这篇文章能帮到你。

好吧,在v友的指导下还是找出了js sdk,里面有分片上传的代码,地址:js sdk,看来下次还是要先找文档,文档找错了也挺尴尬的。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值