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

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

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

这类有两种方案:第一种,是调整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/";
    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( '<div id="' + file.id + '" class="item">' +
            '<h4 class="info">' + file.name + '</h4>' +
            '<p class="state">等待上传...</p>' +
        '</div>' );
    });

    // 文件上传过程中创建进度条实时显示。
    uploader.on( 'uploadProgress', function( file, percentage ) {
        var $li = $( '#'+file.id ),
            $percent = $li.find('.progress .progress-bar');

        // 避免重复创建
        if ( !$percent.length ) {
            $percent = $('<div style="margin:10px 0px" class="progress progress-striped active">' +
              '<div class="progress-bar" role="progressbar" style="width: 0%">' +
              '</div>' +
            '</div>').appendTo( $li ).find('.progress-bar');
        }

        $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的代码都有,这类不再赘述。

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

发布评论

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

 评论(0)

站长头像
chenxing(PHP攻城狮)

运营天数

总访问量

文章数量

-

-

-

交流群:157451741

新浪微博:草莽兴

 近期文章

一年时间又回到这里

 2019-07-27 16:54  53

PHP字符串转数组的三种场景

 2018-05-05 01:32  175

PHP如何遍历字符串?

 2018-05-04 00:56  804

api接口常见的安全问题和解决方案

 2018-05-03 23:20  720

 最新评论

 疯了: 10月10日 13:40
你好呀,我使用docker构建的 把整个项目给了777 并把runtime的所有者给了nginx php的运行者还是报错
来源: thinkphp5的mkdir() Permission denied问题探讨
 mesecretme: 09月30日 15:30
有个问题,有没有发现用redis保存session的话,session清空redis的key还没过期,会依然保留的,这是值变成空了
来源: php项目redis实现session共享案例
 旧久: 09月20日 07:24
感谢!
来源: 没备案域名如何在阿里云服务器上使用?
 pagenoname: 08月24日 18:51
兴哥牛B加油哈兴哥成功的道路上你又进了一步 哈哈
来源: 一年时间又回到这里
 iceyxm: 05月16日 15:00
谜一样的问题,我也遇到了,能改的权限都改了,文件目录属主也改了,然而并没有作用
来源: thinkphp5的mkdir() Permission denied问题探讨
 potatog: 03月27日 15:02
厉害了厉害了,搞了半天我,
来源: thinkphp利用PHPExcel导出数据实践