处理这个问题要先明白,多大的文件才能算是大文件?两三百M算不算大文件。
所谓大小其实是一个相对值。和你所处的网络环境,处理的语言有关系。语言不必多少,网络环境嘛,如果你的上传带宽足够大,那么两三百M不算是太的的文件。当然总有一般情况,就目前普遍的带宽,对于PHP处理上百M的文件就算是大文件。
那么PHP是如何处理大文件上传的?
这类有两种方案:第一种,是调整php.ini对上传文件的限。第二种,制就是切片上传。
如果上传一个上百M的文件,第一种需要调整php.ini的哪些信息呢?我把这些信息做了一些梳理:
max_execution_time = 0; //最久执行时间默认是30秒,0为不做限制
max_input_time = 60; //如果应用程序所运行环境处在低速链路上,则需要增加此值以适应接收数据所需的更多时间。
memory_limit = -1; //本指令设定了一个脚本所能够申请到的最大内存字节数,默认值8M。如果不需要任何内存上的限制,必须将其设为 -1。如果内存不够,则可能出现错误:Fatal error: Allowed * * * memory size of X bytes exhausted (tried to allocate Y bytes)
file_uploads = On;//是否允许通过HTTP上传文件的开关,默认为ON即是开
upload_max_filesize = 300M;//所上传的文件的最大大小。默认值2M
post_max_size = 300M;//设定POST数据所允许的最大大小。此设定也影响到文件上传。要上传大文件,该值必须大于 upload_max_filesize。
以上的配置信息来自度娘的。按照自身的业务需求进行分配。在配置之前可以先看一下php默认的参数,就能够很好的理解第一个问题
来一个我自己用webuploader处理过的案例。
1.修改php.ini配置:按照以上配置修改。
2.前端js部,直接复制webuploader修改
var uploaderArea = (function(){
var webUploaderUrl = "__PUBLIC__/plugins/webuploader/";
var uplaodApi = Global.host + 'Admin/game/webUploader';
var uploader = WebUploader.create({
// swf文件路径
swf: webUploaderUrl + 'Uploader.swf',
// 文件接收服务端。
server: uplaodApi,
// 选择文件的按钮。可选。
// 内部根据当前运行是创建,可能是input元素,也可能是flash.
pick: '#packUpload',
// 不压缩image, 默认如果是jpeg,文件上传前会压缩一把再上传!
resize: false,
})
// 当有文件被添加进队列的时候
uploader.on( 'fileQueued', function( file ) {
$list = $('#fileList');
$list.append( '
'
'
等待上传...
' +'
});
// 文件上传过程中创建进度条实时显示。
uploader.on( 'uploadProgress', function( file, percentage ) {
var $li = $( '#'+file.id ),
$percent = $li.find('.progress .progress-bar');
// 避免重复创建
if ( !$percent.length ) {
$percent = $('
'
' +'
}
$li.find('p.state').text('上传中');
$percent.css( 'width', percentage * 100 + '%' );
});
uploader.on( 'uploadSuccess', function( file,res ) {
$( '#'+file.id ).find('p.state').text('已上传');
$('input[name="package"]').val(res.file.urlpath);
$('input[name="packagesize"]').val(res.file.size);
});
uploader.on( 'uploadError', function( file,res ) {
$( '#'+file.id ).find('p.state').text('上传出错');
});
uploader.on( 'uploadComplete', function( file ) {
$( '#'+file.id ).find('.progress').fadeOut();
});
$('#ctlBtn').click(function(){
uploader.upload();
})
})();
3.服务器端(thinkphp)
/**
* 上传游戏文件接口(原来common中的接口不适用)
* 需要从session中获取游戏ID,动态创建游戏相关目录
*/
public function webUploader(){
if(IS_POST){
$gid = $_SESSION['gid'];
$dir = './Public/upload/games/gid_' . $gid;
$path = pathinfo($_FILES['file']['name']);
$filename = $path['filename'];
if(!is_dir($dir)){
mkdir($dir,0777,true);
}
$config = array(
'maxSize' => 814572800,
'rootPath' => $dir . '/',
'subName' => false,
'saveName' => time() . '_' . $filename
);
$upload = new \Think\Upload($config);// 实例化上传类
// 上传文件
$info = $upload->upload();
if(!$info) {// 上传错误提示错误信息
$this->error($upload->getError());
}else{// 上传成功
$info['file']['urlpath'] = ltrim($upload->rootPath,'.') . $info['file']['savepath'] . $info['file']['savename'];
echo json_encode($info);die;
}
}else{
echo '非法请求';
}
}
利用webuploader调用前端js部分调用服务器端的这个接口,就能非常快速的完成大文件上传的功能。
当然这种方式是耗资源的,瓶颈非常明显。所以有了第二种解决方式。这种方式实现起来复杂了点。webuploader API里有接受,包括后端php的代码都有,这类不再赘述。