php webuploader大文件,JS - 文件上传组件WebUploader使用详解3(大文件的分片、并发上传)...

对于一些大文件,由于服务端请求大小的限制,如果直接上传可能无法上传成功。即使不限制大小也可能因为传输时间过长而超时。

所以要上传大文件,最好的方式就是使用分段上传。即将原始文件分成一片片单独上传(每个分片大小建议 5M左右),服务端这边在所有分片都接收完毕后再将它们合并起来。

1,效果图

(1)这里我上传一个 17M的文件(开启分片上传,单片 4M),客户端这边表面上看不出什么不同。

4666aa4fc16e64b7ff1e675fdedc3102.png

(2)但打开控制台就可以看到,这个文件实际分成了 5 个请求并发提交。

7a3e78514d634aa90c410670c6d7c69e.png

2,样例代码

(1)客户端代码(index.html)这边改动不大,我们只需设置好“开启分片上传”、“每个分片的大小”这两个配置项即可,客户端会自动判断是否需要分片:

如果文件需要分片上传的话:在每个分片文件上传的同时,还会自动带上 chunks和 chunk两个参数,它们分别代表分片数和当前分片索引。

如果文件不需要分片的话:逻辑和不开启分片一样(也没有 chunks和 chunk两个参数)

$(function() {

//开始上传按钮

var $btn = $('#ctlBtn');

//文件信息显示区域

var $list = $('#thelist');

//当前状态

var state = 'pending';

//初始化Web Uploader

var uploader = WebUploader.create({

// swf文件路径

swf: 'webuploader/Uploader.swf',

// 文件接收服务端。

server: 'http://www.hangge.com/upload.php',

// 选择文件的按钮。可选。

// 内部根据当前运行是创建,可能是input元素,也可能是flash.

pick: '#picker',

// 开启分片上传。

chunked: true,

//每个分片的大小(这里设为4M)

chunkSize:4*1024*1024

});

// 当有文件被添加进队列的时候(选择文件后调用)

uploader.on( 'fileQueued', function( file ) {

$list.append( '

' +

'

' + file.name + '
' +

'

等待上传...

' +

'

' );

});

// 文件上传过程中创建进度条实时显示。

uploader.on( 'uploadProgress', function( file, percentage ) {

var $li = $( '#'+file.id );

$li.find('p.state').text('上传中(' + parseInt(percentage * 100) + '%)');

});

// 文件上传成功后会调用

uploader.on( 'uploadSuccess', function( file ) {

$( '#'+file.id ).find('p.state').text('已上传');

});

// 文件上传失败后会调用

uploader.on( 'uploadError', function( file ) {

$( '#'+file.id ).find('p.state').text('上传出错');

});

// 文件上传完毕后会调用(不管成功还是失败)

uploader.on( 'uploadComplete', function( file ) {

$( '#'+file.id ).find('.progress').fadeOut();

});

// all事件(所有的事件触发都会响应到)

uploader.on( 'all', function( type ) {

if ( type === 'startUpload' ) {

state = 'uploading';

} else if ( type === 'stopUpload' ) {

state = 'paused';

} else if ( type === 'uploadFinished' ) {

state = 'done';

}

if ( state === 'uploading' ) {

$btn.text('暂停上传');

} else {

$btn.text('开始上传');

}

});

// 开始上传按钮点击事件响应

$btn.on( 'click', function() {

if ( state === 'uploading' ) {

uploader.stop();

} else {

uploader.upload();

}

});

});

#picker {

display: inline-block;

}

#ctlBtn {

position: relative;

display: inline-block;

cursor: pointer;

background: #EFEFEF;

padding: 10px 15px;

color: #2E2E2E;

text-align: center;

border-radius: 3px;

overflow: hidden;

}

#ctlBtn:hover {

background: #DDDDDD;

}

选择文件
开始上传

(2)服务端代码(upload.php)这边复杂些:

如果上传的文件没有分片,那么就直接保存(逻辑和以前一样)

如果上传的是单个分片,那么将分片保存到 tmp文件夹下,命名为“文件名.tmp*”(* 号为该分片索引)

每次分片保存后会判断 tmp文件夹下是否所有分片都已经有了,是的话则合并成完整文件,并删除 tmp文件夹下的临时文件。

//获取文件名

$name = $_POST["name"];

//获取大小

$size = $_POST["size"];

//获取文件类型

$type= $_POST["type"];

//获取文件最后修改时间

$lastModifiedDate= $_POST["lastModifiedDate"];

//获取分片总数

$chunks= $_POST["chunks"];

//获取当前分片索引

$chunk= $_POST["chunk"];

// 文件保存路径

$upload = $_SERVER["DOCUMENT_ROOT"]."/uploadFiles";

// 临时文件保存路径(分片)

$tmp = $_SERVER["DOCUMENT_ROOT"]."/uploadFiles/tmp";

// 判断文件夹是否存在,不存在则创建

if (!is_dir($tmp)){ mkdir($tmp, 0777, true); }

//如果不分片的话直接保存

if (!isset($chunks)) {

//将上传的文件保存到指定目录下

move_uploaded_file($_FILES["file"]["tmp_name"], $upload."/".$name);

//输出信息

echo "--- 文件上传完毕 ---\n";

echo "文件名:".$name."\n";

echo "文件大小:".$size."\n";

echo "文件类型:".$type."\n";

echo "文件最后修改时间:".$lastModifiedDate;

} else {

// 如果分片的话先把分片存储到tmp文件夹下

move_uploaded_file($_FILES["file"]["tmp_name"], $tmp."/".$name.".tmp".$chunk);

echo "--- 分片上传完毕 ---\n";

// 判断所有分片是否都上传完毕了

$complete = true;

for($i = 0; $i < $chunks; $i++) {

if(!file_exists($tmp."/".$name.".tmp".$i)){

$complete = false;

break;

}

}

//如果所有分片都有的话就开始合并

if ($complete) {

$fp = fopen($upload."/".$name, "ab");

for($i = 0; $i < $chunks; $i++) {

$tmp_file = $tmp."/".$name.".tmp".$i;

$handle = fopen($tmp_file, "rb");

fwrite($fp, fread($handle, filesize($tmp_file)));

fclose($handle);

unset($handle);

unlink($tmp_file);//合并完毕的文件就删除

}

echo "--- 文件合并完毕 ---\n";

}

}

?>

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值