专注WEB开发 分享经验,沉淀知识

快速解决php大文件上传问题

 作者:chenxing  时间:2017-01-19 18:56  评论:

这类有两种方案:第一种,是调整php.ini对上传文件的限。第二种,制就是切片上传。

处理这个问题要先明白,多大的文件才能算是大文件?两三百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/";
ovar uplaodApi = Global.host + 'Admin/game/webUploader';
o
ovar uploader = WebUploader.create({

o    // swf文件路径
o    swf: webUploaderUrl + 'Uploader.swf',
o
o    // 文件接收服务端。
o    server: uplaodApi,
o
o    // 选择文件的按钮。可选。
o    // 内部根据当前运行是创建,可能是input元素,也可能是flash.
o    pick: '#packUpload',
o
o    // 不压缩image, 默认如果是jpeg,文件上传前会压缩一把再上传!
o    resize: false,
o    
o})
o
o// 当有文件被添加进队列的时候
ouploader.on( 'fileQueued', function( file ) {
o$list = $('#fileList');
o    $list.append( '<div id="' + file.id + '" class="item">' +
o        '<h4 class="info">' + file.name + '</h4>' +
o        '<p class="state">等待上传...</p>' +
o    '</div>' );
o});
o
o// 文件上传过程中创建进度条实时显示。
ouploader.on( 'uploadProgress', function( file, percentage ) {
o    var $li = $( '#'+file.id ),
o        $percent = $li.find('.progress .progress-bar');
o
o    // 避免重复创建
o    if ( !$percent.length ) {
o        $percent = $('<div style="margin:10px 0px" class="progress progress-striped active">' +
o          '<div class="progress-bar" role="progressbar" style="width: 0%">' +
o          '</div>' +
o        '</div>').appendTo( $li ).find('.progress-bar');
o    }
o
o    $li.find('p.state').text('上传中');
o
o    $percent.css( 'width', percentage * 100 + '%' );
o});
o
ouploader.on( 'uploadSuccess', function( file,res ) {
o    $( '#'+file.id ).find('p.state').text('已上传');
o    $('input[name="package"]').val(res.file.urlpath);
o    $('input[name="packagesize"]').val(res.file.size);
o    
o});
o
ouploader.on( 'uploadError', function( file,res ) {
o    $( '#'+file.id ).find('p.state').text('上传出错');
o});
o
ouploader.on( 'uploadComplete', function( file ) {
o    $( '#'+file.id ).find('.progress').fadeOut();
o});
o$('#ctlBtn').click(function(){
ouploader.upload();
o})
o
})();

3.服务器端(thinkphp)

/**
 * 上传游戏文件接口(原来common中的接口不适用)
 * 需要从session中获取游戏ID,动态创建游戏相关目录
 */
 public function webUploader(){
 if(IS_POST){
 $gid = $_SESSION['gid'];
o$dir = './Public/upload/games/gid_' . $gid;
o$path = pathinfo($_FILES['file']['name']);
o$filename = $path['filename'];
oif(!is_dir($dir)){
omkdir($dir,0777,true);
o}
 $config = array(
o    'maxSize'    =>     814572800,
o    'rootPath'   =>     $dir . '/',
o    'subName'    =>false,
o    'saveName' =>time() . '_' . $filename
o);
o$upload = new \Think\Upload($config);// 实例化上传类
o    // 上传文件 
o    $info   =   $upload->upload();
     if(!$info) {// 上传错误提示错误信息
o        $this->error($upload->getError());
o    }else{// 上传成功
o    $info['file']['urlpath'] = ltrim($upload->rootPath,'.') . $info['file']['savepath'] . $info['file']['savename'];
o        echo json_encode($info);die;
o    }
o}else{
oecho '非法请求';
o}
o
}

利用webuploader调用前端js部分调用服务器端的这个接口,就能非常快速的完成大文件上传的功能。

当然这种方式是耗资源的,瓶颈非常明显。所以有了第二种解决方式。这种方式实现起来复杂了点。webuploader API里有接受,包括后端php的代码都有,这类不再赘述。

除特别注明外,本站所有文章均为作者原创。 或分享自己的编程经验,或探讨工作中的问题,或聊以人生趣事。 转载请注明出处来自 http://www.qiusuoweb.com/25.html

发布评论

 提交评论
有人回复时邮件通知我

 评论(0)

站长头像
chenxing(PHP攻城狮)

运营天数

总访问量

文章数量

-

-

-

交流群:157451741

新浪微博:草莽兴

 近期文章

个人博客图片免费存放解决方案

 2022-03-21 00:16  92

MySQL中的MVCC总结

 2022-03-19 03:00  94

什么才是高级工程师的第一技能

 2022-03-16 22:04  71

 最新评论

 诚心: 09月29日 23:01
学到了
来源: 如何一次性推送百万级别的消息
 Nick: 04月14日 12:26
网上的资料还是太老,都只是取一个元素,解决了一大难题
来源: redis set集合取出一组数据并删除
 skywalker: 11月03日 18:21
简洁明了
来源: mysql 获取某个日期的前一天或后一天
 lisheng: 05月09日 19:26
兴哥牛B加油哈兴哥成功的道路上你又进了一步 哈哈
来源: 一年时间又回到这里
 心态炸裂: 03月24日 10:54
No3.blindcomfirm 多了一个l,望改正!!!
来源: 微信小程序获取input值的总结
 666666: 11月08日 13:49
66666
来源: 一年时间又回到这里