php js框上传文件,php+js实现文件分块上传

我们在上传大文件时,可能会由于服务器的原因导致文件上传失败,文件过大时由于服务器的配置或响应事件过长导致上传文件失败,这时候我们可以将一个大的文件分为若干块,然后分批次上传到服务端,当所有文件块上传完成后再由服务器将各个文件块整合成我们上传的文件

一:分块上传流程:

1:由前端js将上传的文件信息进行切割成若干块,然后循环将若干块的文件块上传到服务端

2:服务端接收到文件块信息后保存起来,当所有文件块上传完毕后,将所有上传的文件块整合成文件并保存起来

二:实现代码:

1:HTML

上传进度:

2:JS//获取节点

var fileForm = document.getElementById("file");

var uploadBtn = document.getElementById('upload');

var stopBtn = document.getElementById('stop');

var restartBtn = document.getElementById('restart');

//定义常量

const LENGTH = 100 * 1024;//每个上传的文件块大小(100KB)

var start = 0;

var end = LENGTH + start;

var blob;

var is_stop = 0;

var blob_num = 1;

var file = null;

var upload_instance = new Upload();

//上传事件

uploadBtn.onclick = function () {

upload_instance.addFileAndSend(fileForm);

return false;

}

stopBtn.onclick = function () {

upload_instance.stop();

return false;

}

restartBtn.onclick = function () {

upload_instance.start();

return false;

}

function Upload() {

//判断浏览器类型

if (window.XMLHttpRequest){

//IE7+, Firefox, Chrome, Opera, Safari

var xhr=new XMLHttpRequest();

}else{

//IE6, IE5

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

}

//上传文件

this.addFileAndSend = function (that) {

file = that.files[0];

blob = cutFile(file);

//上传

uploadFile(blob, file);

blob_num += 1;

}

//停止文件上传

this.stop = function () {

xhr.abort();

is_stop = 1;

}

this.start = function () {

uploadFile(blob, file);

is_stop = 0;

}

//切割文件

function cutFile(file) {

var file_blob = file.slice(start, end);

start = end;

end = start + LENGTH;

return file_blob;

};

//上传文件

function uploadFile(blob, file) {

var form_data = new FormData();

var total_blob_num = Math.ceil(file.size / LENGTH);

//上传文件信息

form_data.append('file', blob);

//上传的第几个文件块

form_data.append('blob_num', blob_num);

//总文件块数

form_data.append('total_blob_num', total_blob_num);

//文件名称

form_data.append('file_name', file.name);

//上传

xhr.open('POST', './test.php', false);

xhr.onreadystatechange = function () {

//获取上传进度

if (total_blob_num == 1) {

progressText = '100%';

} else {

progressText = (Math.min(100, (blob_num / total_blob_num) * 100)).toFixed(2) + '%';

}

var progress = document.getElementById('progress');

progress.innerHTML = progressText;

//循环执行上传,直到所有文件块上传完成

var t = setTimeout(function () {

if (start < file.size && is_stop == 0) {

blob = cutFile(file);

uploadFile(blob, file);

blob_num += 1;

} else {

//所有文件块上传完成

}

}, 1000);

}

xhr.send(form_data);

//每次文件块上传后,清空上传信息

form_data = "";

}

}

3:PHP

(1):上传类:class Upload

{

/**

* @var string 上传目录

*/

private $filepath = './upload'; //上传目录

/**

* @var string 块文件临时存储的位置

*/

private $tmpPath;

/**

* @var integer 第几个文件块

*/

private $blobNum;

/**

* @var integer //文件块总数

*/

private $totalBlobNum;

/**

* @var string 上传文件名

*/

private $fileName;

public function __construct($tmpPath, $blobNum,$totalBlobNum,$fileName, $filepath = ''){

if (!empty($filepath)) {

$this->filepath = $filepath;

}

$this->tmpPath = $tmpPath;

$this->blobNum = $blobNum;

$this->totalBlobNum = $totalBlobNum;

$this->fileName = $fileName;

//保存文件块

$this->moveFile();

//保存文件

$this->fileMerge();

}

private function fileMerge(){

//当文件块都上传后将文件块整合成文件

if($this->blobNum == $this->totalBlobNum){

for($i=1; $i<= $this->totalBlobNum; $i++){

$blob = '';

$blob = file_get_contents($this->filepath.'/'. $this->fileName.'__'.$i);

file_put_contents($this->filepath.'/'. $this->fileName, $blob, FILE_APPEND );

unset($blob);

}

//删除文件块

$this->deleteFileBlob();

}

}

//删除文件块

private function deleteFileBlob(){

for($i=1; $i<= $this->totalBlobNum; $i++){

@unlink($this->filepath.'/'. $this->fileName.'__'.$i);

}

}

private function moveFile(){

$this->touchDir();

$filename = $this->filepath.'/'. $this->fileName.'__'.$this->blobNum;

//保存文件块

move_uploaded_file($this->tmpPath,$filename);

}

//上传返回

public function uploadReturn(){

if($this->blobNum == $this->totalBlobNum){

if(file_exists($this->filepath.'/'. $this->fileName)){

return [

'code' => 2,

'message' => 'success',

'file_path' => 'http://'.$_SERVER['HTTP_HOST'].str_replace('.','',$this->filepath).'/'. $this->fileName,

'local_path' => str_replace('.','',$this->filepath).'/'. $this->fileName

];

}

}

return [

'code' => 1,

'message' => 'waiting',

];

}

/**

* 创建目录

*/

private function touchDir(){

if(!file_exists($this->filepath)){

return mkdir($this->filepath);

}

}

}

调用上传类$tmpName = $_FILES['file']['tmp_name'];

$blobNum = $_POST['blob_num'];

$totalBlobNum = $_POST['total_blob_num'];

$fileName = $_POST['file_name'];

$upload = new Upload($tmpName, $blobNum, $totalBlobNum, $fileName);

$data = $upload->uploadReturn();

header('Content-type: application/json');

return json_encode($data);

根据如上步骤就可以实现将文件分成若干块进行上传功能

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值