100字范文,内容丰富有趣,生活中的好帮手!
100字范文 > html5 PHP 分片上传 PHP大文件分割上传(分片上传)

html5 PHP 分片上传 PHP大文件分割上传(分片上传)

时间:2021-12-30 12:31:34

相关推荐

html5 PHP 分片上传 PHP大文件分割上传(分片上传)

问题:

请问如何上传比较大的文件?

服务端为什么不能直接上传大文件?跟php.ini 里面几个配置有很大的关系。

upload_max_filesize

post_max_size

memory_limit

max_execute_time

当然不能简单粗暴的将这几个参数调大,否则服务器会出现内存资源吃光是早晚的的问题。

解决思路

好在HTML5开放了新的FILE API,也可以直接操作二进制对象,我们可以直接在浏览器端实现文件切割,

按照以前的做法就得用Flash的方案,实现起来会麻烦很多。

JS思路

1.监听上传按钮的onchange事件

2.获取文件的FILE对象

3.把文件的FILE对象进行切割,并且附加到FORMDATA对象中

4.把FORMDATA对象通过AJAX发送到服务器

5.重复3、4步骤,直到文件发送完。

PHP思路

1.建立上传文件夹

2.把文件从上传临时目录移动到上传文件夹//移动文件

privatefunctionmoveFile(){

$this->touchDir();

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

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

}

3.所有的文件块上传完成后,进行文件合成privatefunctionfileMerge(){

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

$blob='';

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

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

}

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

$this->deleteFileBlob();

}

}

4.删除文件夹//删除文件块

privatefunctiondeleteFileBlob(){

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

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

}

}

5.返回上传后的文件路径//API返回数据

publicfunctionapiReturn(){

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

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

$data['code']=2;

$data['msg']='success';

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

}

}else{

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

$data['code']=1;

$data['msg']='waitingforall';

$data['file_path']='';

}

}

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

echojson_encode($data);

}

upload.htmlhtml>

content="width=device-width,user-scalable=no,initial-scale=1.0,maximum-scale=1.0,minimum-scale=1.0">

Document

#progress{

width:300px;

height:20px;

background-color:#f7f7f7;

box-shadow:inset01px2pxrgba(0,0,0,0.1);

border-radius:4px;

background-image:linear-gradient(tobottom,#f5f5f5,#f9f9f9);

}

#finish{

background-color:#149bdf;

background-image:linear-gradient(45deg,rgba(255,255,255,0.15)25%,transparent25%,transparent50%,rgba(255,255,255,0.15)50%,rgba(255,255,255,0.15)75%,transparent75%,transparent);

background-size:40px40px;

height:100%;

}

form{

margin-top:50px;

}

varfileForm=document.getElementById("file");

varstopBtn=document.getElementById('stop');

varupload=newUpload();

fileForm.onchange=function(){

upload.addFileAndSend(this);

}

stopBtn.onclick=function(){

this.value="停止中";

upload.stop();

this.value="已停止";

}

functionUpload(){

varxhr=newXMLHttpRequest();

varform_data=newFormData();

//constLENGTH=1024*1024;

constLENGTH=10*10;

varstart=0;

varend=start+LENGTH;

varblob;

varblob_num=1;

varis_stop=0

//对外方法,传入文件对象

this.addFileAndSend=function(that){

varfile=that.files[0];

blob=cutFile(file);

sendFile(blob,file);

blob_num+=1;

}

//停止文件上传

this.stop=function(){

xhr.abort();

is_stop=1;

}

//切割文件

functioncutFile(file){

varfile_blob=file.slice(start,end);

start=end;

end=start+LENGTH;

returnfile_blob;

};

//发送文件

functionsendFile(blob,file){

vartotal_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','./upload.php',false);

xhr.onreadystatechange=function(){

varprogress;

varprogressObj=document.getElementById('finish');

if(total_blob_num==1){

progress='100%';

}else{

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

}

progressObj.style.width=progress;

vart=setTimeout(function(){

if(start

blob=cutFile(file);

sendFile(blob,file);

blob_num+=1;

}else{

setTimeout(t);

}

},1000);

}

xhr.send(form_data);

}

}

upload.php<?php

classUpload{

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

private$tmpPath;//PHP文件临时目录

private$blobNum;//第几个文件块

private$totalBlobNum;//文件块总数

private$fileName;//文件名

publicfunction__construct($tmpPath,$blobNum,$totalBlobNum,$fileName){

$this->tmpPath=$tmpPath;

$this->blobNum=$blobNum;

$this->totalBlobNum=$totalBlobNum;

$this->fileName=$fileName;

$this->moveFile();

$this->fileMerge();

}

//判断是否是最后一块,如果是则进行文件合成并且删除文件块

privatefunctionfileMerge(){

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

$blob='';

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

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

}

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

$this->deleteFileBlob();

}

}

//删除文件块

privatefunctiondeleteFileBlob(){

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

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

}

}

//移动文件

privatefunctionmoveFile(){

$this->touchDir();

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

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

}

//API返回数据

publicfunctionapiReturn(){

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

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

$data['code']=2;

$data['msg']='success';

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

}

}else{

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

$data['code']=1;

$data['msg']='waitingforall';

$data['file_path']='';

}

}

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

echojson_encode($data);

}

//建立上传文件夹

privatefunctiontouchDir(){

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

returnmkdir($this->filepath);

}

}

}

//实例化并获取系统变量传参

$upload=newUpload($_FILES['file']['tmp_name'],$_POST['blob_num'],$_POST['total_blob_num'],$_POST['file_name']);

//调用方法,返回结果

$upload->apiReturn();

项目版本二:

何为大文件切割上传?

原理:利用HTML5的新特性,将文件内容切割成分段的二进制信息,然后每次向服务器上传一段,而服务器,只需要把我们每次上传的二进制信息整合存储到一个文件中,那么最后这个文件就是所上传的文件。

由于php.ini默认的上传大小为2M,如果每批都上传2M,我测试的时候时间比较长,这里我将其限制大小该为20M,最大post数据为28M,便于测试。如果实际开发中不能修改其参数,则每批上传的数据不能超过最大限制。

post_max_size=28M

upload_max_filesize=20M

我的是在nginx里面上传所以还需要修改Nginx配置文件/etc/nginx/nginx.con

//在http{} 里面加即可

client_max_body_size50m#客户端最大上传大小50M

JavaScript中的File对象

在之前的文章中我们已经使用到了这个Api,File对象中保存了文件的大小、名称、类型等信息

JavaScript中的Blob对象

Blob对象是二进制对象,也是File对象的父类,Blob对象中有一个很重要的方法:slice() 方法,利用这个方法我们可以把文件内容切割成二进制信息。slice() 方法接受三个参数,起始偏移量,结束偏移量,还有可选的 mime 类型。如果 mime 类型,没有设置,那么新的 Blob 对象的 mime 类型和父级一样。html>

大文件切割上传

functionselfile(){

constLENGTH=1024*1024*10;//每次上传的大小

varfile=document.getElementsByName('video')[0].files[0];//文件对象

varfilename=document.getElementsByName('video')[0].files[0].name;

vartotalSize=file.size;//文件总大小

varstart=0;//每次上传的开始字节

varend=start+LENGTH;//每次上传的结尾字节

varfd=null//创建表单数据对象

varblob=null;//二进制对象

varxhr=null;//xhr对象

while(start

fd=newFormData();//每一次需要重新创建

xhr=newXMLHttpRequest();//需要每次创建并设置参数

xhr.open('POST','upload.php',false);

blob=file.slice(start,end);//根据长度截取每次需要上传的数据

fd.append('video',blob);//添加数据到fd对象中

fd.append('filename',filename);//获取文件的名称

xhr.send(fd);//将fd数据上传

//重新设置开始和结尾

start=end;

end=start+LENGTH;

}

}

大文件切割上传

接收数据页面upload.php:

/**

*大文件切割上传,把每次上传的数据合并成一个文件

*/

$filename='./uploads/'.$_POST['filename'];//确定上传的文件名

//第一次上传时没有文件,就创建文件,此后上传只需要把数据追加到此文件中

if(!file_exists($filename)){

move_uploaded_file($_FILES['video']['tmp_name'],$filename);

}else{

file_put_contents($filename,file_get_contents($_FILES['video']['tmp_name']),FILE_APPEND);

}

?>

测试之前,先创建uploads文件夹

如果是linux系统的话 切记给uploads给权限

sudo chmod -R 777 uoloads/ //赋予uploads文件夹 777 权限 -R 递归子文件

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。