php 切割上传,[原创]用XHR2实现大文件的切割上传(分块上传)

首先要截取上传动作,并用JS获取到要上传的文件资源,我们要用:

var fileobj =

document.getElementByTagName('input')[i].files[0];

来获取上传的文件资源,然后通过它这个对象里面继承的一个slice()方法来对二进制文件进行切割,每次切割的大小是在JS里设定的

这个过程里面关键问题有两点:

1、要把文件按顺序依次切割并依次发送到服务器

2、服务器接收到的是一块一块的二进制文件块,要把这些文件块按顺序组合到一起

对于第一点,我们的做法是,关闭ajax的异步上传,并用while()循环不断切割,在while中记录每次切割的起始和结束位置(位置是按字节算的,1MB要换算成1*1024*1024字节),然后依次send(),这里面要注意的问题有三点:

1、要在while前获取到文件总大小,这个通过fileobj.size可以得到。

2、ajax对象要每次循环时重新创建,否则当第一次send()完毕后,状态变为4,就发送完毕不会再发送后续文件了

3、被切割的数据依然要用FormData对象来append打包发送,否则服务器不认识这是文件数据

关键代码如下:

const SLICESIZE = 10 * 1024 * 1024;//每次切割的大小,这里是10MB

var start = 0;

var end = 0;

totalsize = fileobj.size;

while(start < totalsize){

start = end ;

end = start + SLICESIZE;

var xhr = new XMLHttpRequest();

var fd = new FormData();

var part

= fileobj.slice(start,end);//对文件进行切割,两个参数

fd.append('name',part);//把切割文件打包进FormData对象中以便发送,其中name的值就是服务器$_FILES['name']接受处的变量名

xhr.open('POST','test.php',false);//之所以关闭异步,是为了防止文件块送达服务器的顺序出错

xhr.send(fd);//把打包的数据发送

}

对于第二点,由于我们在ajax处已经关闭了异步,所以只需要把收到的文件块以append的方式追加到接受文件里即可,当所有文件块都追加完毕,则整个大文件就接受完毕了。

这个过程里关键问题有两点:

1、对于接受到的文件,我们要用file_get_contents()函数读取它的文件数据

2、读取完文件数据后,我们用file_put_contents()以APPEND追加的方式加入到保存的文件

这个地方保存的文件可能在第一次接收的时候不存在,所以需要用file_exists()判断一下,如果不存在的话,就把接收到的文件通过move_uploaded_file()把第一次传的文件移动到指定位置并命名,然后,后续再传上来的文件,就以APPEND追加进这个文件就OK了

关键代码:

//判断

file_put_contents('./upload/demo.mov',file_get_contents($_FILES['name']['tmp_name']),FILE_APPEND);

另外有一点值得补充:

由于JS是单线程的,加上浏览器的渲染原理,导致如果再ajax异步被关闭的情况下进行分块传送大文件,将造成两个明显的问题:

1、传送大文件所需的时间比较长。

2、ajax异步被关闭后,直到大文件全部传送完毕,后续程序,至少该函数才会结束。

那么这里有个问题就是关于动态改变CSS来处理进度条的问题,根据浏览器的渲染原理,如果JS某个函数一直处于执行状态,那么由此导致的一切可能造成浏览器repain的操作都得等到JS函数执行完毕后进行,期间,浏览器会把所有repain操作积蓄起来,等到JS执行完毕后,统一一次全部完成,所以这个地方的进度条设计要用到setInterval()来规定间隔多长时间触发一次计算和渲染才行

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值