Webupload+PHP上传大文件

今天来写写上传文件这件‘小事’

本文把我以前编写上传文件记录一下,给以后的自己备用和吐槽


需要用到的东西

开始

引入webupload.js

<script type="text/javascript" src="./webupload/webuploader.js"></script>

然后修改样式,我的样式如下:

这里写图片描述

* {
    -webkit-box-sizing: border-box;
    -moz-box-sizing: border-box;
    box-sizing: border-box;
}
.fl{
    float: left;
}
.fr{
    float: right;
}
label {
    display: inline-block;
    max-width: 100%;
    margin-bottom: 5px;
    font-weight: 700;
}
/*按钮*/
#picker {
    width: 100px;
    height: 100px;
    background: #eee;
    border: 1px solid #cacaca;
}
#picker .webuploader-pick {
    background: #eee!important;
    width: 100%!important;
    height: 100%!important;
    line-height: 98px;
    font-size: 18px;
    color: #999;
    padding: 0;
}
.webuploader-element-invisible {
    position: absolute !important;
    clip: rect(1px 1px 1px 1px);
    clip: rect(1px,1px,1px,1px);
}
.webuploader-container {
    position: relative;
    display: inline-block;
    vertical-align: top;
}
.webuploader-pick {
    position: relative;
    display: inline-block;
    cursor: pointer;
    background: #3bb4f2;
    padding: 4px 12px;
    color: #fff;
    text-align: center;
    border-radius: 3px;
    overflow: hidden;
}
/*上传列表*/
.item{
    width: 300px;
    height: 70px;
    background: #F1F1F1;
    border: 1px solid #c3c3c3;
    padding: 5px 10px;
    position: relative;
    font-size: 14px;
    color: #545454;
    margin-bottom: 15px;
    box-sizing: content-box;
}
.item h4{
    margin: 0 0 6px;
    font-size: 16px;
    width: 180px;
    height: 22px;
    line-height: 22px;
    white-space:nowrap;
    -ms-text-overflow: ellipsis;
    text-overflow: ellipsis;
    overflow: hidden;
}
.item .progress{
    height: 5px;
    width: 100%;
    margin: 0;
    background: #aaa;
}
.item .progress-bar{
    height: 100%;
    background: #676565;
    width: 0;
}
.item .start_upload{

}
.item .progress-txt{
    margin-top:10px;
    width: 200px;
    height: 26px;
    line-height: 26px;
    overflow: hidden;
    white-space:nowrap;
    -ms-text-overflow: ellipsis;
    text-overflow: ellipsis;
    overflow: hidden;
}
.item .del_upload{
    position: absolute;
    right: 10px;
    top: 5px;
    cursor: pointer;
}
.item .del_upload:hover{
    color: #333;
    font-weight: 600;
}
.item .stop_upload,.start_upload,.again_upload,.continue_upload{
    width: 83px;
    margin-top: 10px;
    height: 26px;
    line-height: 26px;
    text-align: center;
    background: #d8d8d8;
    border-radius: 3px;
    display: none;
    cursor: pointer;
}
.item .stop_upload:hover,.start_upload:hover,.again_upload:hover,.continue_upload:hover{
    background: #cacaca;
}
.item .current{
    display: block;
}

html

<!DOCTYPE HTML>
<html>
<head>
    <meta charset="utf-8">
    <meta name="renderer" content="webkit|ie-comp|ie-stand">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no" />
    <meta http-equiv="Cache-Control" content="no-siteapp" />
    <link href="default.css" rel="stylesheet" type="text/css" />
    <title>上传文件</title>
</head>
<body>
<div id="imgUploadCtn">
    <div class="btns">
        <div id="picker">选择文件</div>
        <div id="thelist" class="uploader-list"></div>
        <div id="imgCtn"></div>
    </div>
</div>
<script src="jquery-2.1.1.min.js"></script>
<script src="./webupload/webuploader.js"></script>
<script src="default.js"></script>
</body>
</html>

js

$(function () {

    var uploader = WebUploader.create({
        // swf文件路径
        swf: './webupload/Uploader.swf',
        // 文件接收服务端。
        server: './fileUpload_set',
        //后缀名验证
        accept:{
            title:'zip',
            extensions:'zip',
            mimeTypes:'.zip'
        },
        //分片上传
        chunked:true,
        //分片上传大小  这是2M
        chunkSize:1024*1024*2,
        //文件并发数 因为是分片有排序规则所以并发数为1
        threads:1,
        // 选择文件的按钮。可选。
        // 内部根据当前运行是创建,可能是input元素,也可能是flash.
        pick: '#picker',
        //限制文件总数
        fileNumLimit:1,
        // 不压缩image, 默认如果是jpeg,文件上传前会压缩一把再上传!
        resize: false
    })
    // 当有文件被添加进队列的时候
    var $list=$('#thelist');
    //随机码
    var randCode='';
    uploader.on( 'fileQueued', function( file ) {
        $list.append( '<div id="' + file.id + '" class="item">' +
            '<h4 class="info">' + file.name + '</h4>' +
            '<div class="progress progress-striped active">' +
            '<div class="progress-bar" role="progressbar"></div></div>'+
            '<div class="state progress-txt fl" title="">等待上传...</div>' +
            '<div id="' + file.id + '_del" class="del_upload fr" data-id="' + file.id + '">删除</div>' +
            '<div id="' + file.id + '_stop" class="stop_upload fr" data-id="' + file.id + '">停止</div>' +
            '<div id="' + file.id + '_continue" class="continue_upload fr" data-id="' + file.id + '">继续</div>' +
            '<div id="' + file.id + '_upload" class="start_upload fr current" data-id="' + file.id + '">开始上传</div>' +
            '<div id="' + file.id + '_again" class="again_upload fr " data-id="' + file.id + '">重新上传</div>' +
            '</div>');
        //删除
        $list.on('click','#'+file.id+'_del',function () {
            uploader.cancelFile(file);
            $(this).closest('.item').remove();
        });
        //停止
        $list.on('click','#'+file.id+'_stop',function () {
            $(this).removeClass('current');
            $(this).parent('.item').find('.again_upload').addClass('current');
            /*uploader.stop(file);*/
            uploader.cancelFile(file);
            console.log(uploader.getStats());
        })
        //继续上传
        $list.on('click','#'+file.id+'_continue',function () {
            $(this).removeClass('current');
            $(this).parent('.item').find('.stop_upload').addClass('current');
            uploader.upload(file);
        })
        //开始上传
        $list.on('click','#'+file.id+'_upload',function () {
            $(this).removeClass('current');
            $(this).parent('.item').find('.stop_upload').addClass('current');
            randCode=rand(15);
            uploader.upload(file);

        })
        //重传
        $list.on('click','#'+file.id+'_again',function () {
            $(this).removeClass('current');
            $(this).parent('.item').find('.stop_upload').addClass('current');
            randCode=rand(15);
            uploader.upload(file.id);
        });

    });
    // 文件上传过程中创建进度条实时显示。
    uploader.on( 'uploadProgress', function( file, percentage ) {
        var $li = $( '#'+file.id ),
            $percent = $li.find('.progress .progress-bar');
        // 避免重复创建
        if ( !$percent.length ) {
            $percent = $('<div class="progress progress-striped active">' +
                '<div class="progress-bar" role="progressbar" style="width: 0%">' +
                '</div>' +
                '</div>').appendTo( $li ).find('.progress-bar');
        }
        $li.find('.state').text('上传中 - '+parseInt(percentage * 100) + '%');
        $percent.css( 'width', parseInt(percentage * 100) + '%' );
    });

    //文件成功处理
    uploader.on( 'uploadSuccess', function( file ,data) {
        //data 为服务器返回的数据
        //console.log(data);
        if(data.status=='ok'){
            if ($('#successInfo').length){
                $('#successInfo').remove();
            }
            $('<div id="successInfo"><img src="'+data.info.img+'" alt=""><input type="hidden" name="picupload" value="'+data.info.img+'">' +
                '<input type="hidden" name="fileupload" value="'+data.info.zip+'"></div>').appendTo('#imgCtn');
            $( '#'+file.id ).find('.state').text('上传完成 - 100%');
            subTime();
        }else{
            $( '#'+file.id ).find('.state').text(data.info);
        };
    });

    //文件失败处理
    uploader.on( 'uploadError', function( file ) {
        $( '#'+file.id ).find('p.state').text('上传出错');
    });

    //上传失败获成功都会执行
    uploader.on('uploadComplete',function (file) {
        $('#'+file.id).find('.current').removeClass('current');
        $('#'+file.id).find('.again_upload').addClass('current');
    })
    //文件加入队列前执行
    uploader.on('beforeFileQueued', function (file) {

    });

    //主要用来询问是否要添加附带参数,大文件在开起分片上传的前提下此事件可能会触发多次
    uploader.on('uploadBeforeSend',function (file,data) {
        //随机码
        data.randCode=randCode;
    });
    //当所有文件上传完成
    uploader.on('uploadFinished',function (file,data) {

    });

    //开始上传
    $('#ctlBtn').on('click', function() {
        uploader.upload();
    });

    // 初始化以后添加 参数
    //uploader.options.formData.uid = 456789;

    //随机码
    function rand(i) {
        var str='123456789qwertyiopasdfghjklzxcvbnm';
        var strLen=str.length;
        var newStr='';
        Math.random()*strLen;
        while(i>0){
            newStr+=str[parseInt(Math.random()*strLen)];
            i--;
        }
        return newStr;
    }

    var t;
    function subTime() {
        var i=100;
        if (t){
            clearInterval(t);
        }
        t=setInterval(function () {
            $('#submit span').text('('+i+'秒后)自动提交');
            if (i==0){
                clearInterval(t);
                $('#submit span').text('提交作品');
                $('#submit').click();
                return;
            };
            i--;
        },1000);
    }


})

PHP代码

<?
//文件上传
public function fileUpload_set(){
    $path="./file/cookie/zip";
    $imgPath="./file/cookie/img/";
    $maxSize=20*1024*1024;
    $exts=['zip'];

    $file=new FileUploadClass();
    /**
     * 上传文件
     * @param $mPath           保存地址
     * @param string $mMaxSize 限制文件大小   单位b
     * @param array  $mExts    限制文件格式 array
     * @return bool
     */
    $msg=$file->fileSave($path,$imgPath,$maxSize,$exts);
    return $this->msg($msg['status'],$msg['info']);
}
?>

PHP合并文件类

<?php
/**
 * Created by PhpStorm.
 * User: Administrator
 * Date: 2017-07-13
 * Time: 上午 11:14
 */


class FileUploadClass
{
    public $msg=[];

    /**
     * 上传文件
     * @param $mPath           保存地址
     * @param string $mMaxSize 限制文件大小   单位b
     * @param array  $mExts    限制文件格式 array
     * @return bool
     */
    public function fileSave($mPath,$mMaxSize=20*1024*1024,$mExts=[]){
        if (strpos($mPath,'.')!==0){
            $mPath='.'.$mPath;
        }
        $arr=explode('/',$mPath);
        $aimUrl='';
        foreach($arr as $str){
            $aimUrl.=$str.'/';
            if(!file_exists($aimUrl)){
                mkdir($aimUrl,0777);
                chmod($aimUrl,0777);
            }
        }

        if (!file_exists($aimUrl)) {
            $this->msg('error','创建目录失败');
            return false;
        }else{
            $upload = new \org\Upload();
            $upload->maxSize = $mMaxSize;
            if($mExts){
                $upload->exts = $mExts;
            }
            $upload->rootPath = $aimUrl;
            $upload->driver = "Local";
            $upload->saveName = ['uniqid', ''];
            $info = $upload->upload();
            if (!$info) {
                $this->msg('error',$upload->getError());
                return false;
            } else {
                $aimUrl=str_replace('./','/',$aimUrl);
                //这里$infoyn[0]是指你上传第一个图片的信息,你如果上传N个图片就会有$infoyn[N]
                if(isset($info[0]['savepath'])){
                    $filePath=$aimUrl . $info[0]['savepath'] . $info[0]['savename'];
                }else{
                    $filePath=$aimUrl . $info['file']['savepath'] . $info['file']['savename'];
                    //获取文件格式
                    $ext=substr($info['file']['savename'],strrpos($info['file']['savename'],'.'));
                    //文件合并(分片上传)
                    if(!empty($_POST['chunks'])&&$_POST['chunks']!=1){
                        return $this->fileCombine($_POST['randCode'].$ext,$mPath,'.'.$filePath,$info['file']['savename']);
                    }
                }
                $this->msg('ok',$filePath,['fileName'=>$info['file']['name']]);
                return true;
            }
        }
        return true;
    }

    /**
     * 文件合并
     * @param $filename    上传的文件名
     * @param $mPath       缓存文件夹路径
     * @param $filesAddr    文件详细地址
     * @param $savename    保存文件的新名称
     * @return array
     */
    public function fileCombine($filename,$mPath,$filesAddr,$savename){
        $oldPath=$mPath.'/'.$filename;
        $newPath=$mPath.'/'.$savename;

        if (!file_exists($mPath)){
            @mkdir($mPath,0777);
        }
        if(file_put_contents($oldPath,file_get_contents($filesAddr),FILE_APPEND)){
            if ($_POST['chunks']==$_POST['chunk']+1){
                @rename($oldPath,$newPath);
            }
            $this->msg('ok',$newPath);
            @unlink($filesAddr);
            return true;
        }else{
            $this->msg('error','文件合并失败');
            @unlink($filesAddr);
            return false;
        };
    }

    /**
     * 移动文件
     * @param $filePath     文件原路径支持数组{a,b~~},字符串 "a,b,c~~"或 "a"
     * @param $movePath     移动后的目录地址
     * @return array
     */
    function fileMove($filePath,$movePath){

        if(is_string($filePath)){
            $imgArr=explode(',',$filePath);
        }elseif(is_array($filePath)){
            $imgArr=$filePath;
        }else{
            $this->msg('error','文件路径只能为字符串或数组');
            return false;
        }

        foreach ($imgArr as $vo){
            if (!empty($vo)){
                if(strpos($vo,'.')!==0){
                    $vo=".".$vo;
                }
                if(strpos($movePath,'.')!==0){
                    $movePath=".".$movePath;
                }
                if(!file_exists($vo)){
                    $this->msg('error','目标文件不存在');
                    return false;
                }else{
                    $fileName=substr($vo,strrpos($vo,'/')+1);
                    $fileArr=explode('/',$movePath);
                    $aimUrl='';
                    foreach($fileArr as $v){
                        $aimUrl.=$v.'/';
                        if (!file_exists($aimUrl)){
                            if(mkdir($aimUrl,0777,true)){
                                $this->msg('error','创建文件夹失败');
                                return false;
                            };
                            //取得文件最大权限
                            chmod($aimUrl, 0777);
                        }
                    }
                    //移动文件
                    if(!rename($vo , $movePath.$fileName)){
                        $this->msg('error','移动文件失败');
                        return false;
                    };
                }
            }
        }
        $this->msg('ok',$movePath.$fileName);
        return true;
    }

    /**
     * 删除文件
     * @param $dir 删除的文件路径 或 目录
     * @return bool
     */
    function fileDelete($dir){
        if (strpos($dir,'.')!==0){
            $dir='.'.$dir;
        }
        if (filetype($dir)=='dir'){
            if ($dh=opendir($dir)){
                while (($file=readdir($dh))!==false){
                    if($file=='.'||$file=='..'){
                        continue;
                    }
                    if (filetype($dir.'/'. $file)=='dir'){
                        if (!$this->deleteFiles($dir.'/' . $file)){
                            return false;
                        }
                        if(!rmdir($dir.'/'.$file)){
                            $this->msg('error','删除失败('.$dir.'/'.$file.')');
                            return false;
                        }
                    }else{
                        if(!unlink($dir.'/' . $file)){
                            $this->msg('error','删除失败('.$dir.'/'.$file.')');
                            return false;
                        }
                    }

                }
                closedir($dh);
            }
        }else{
            if(!@unlink($dir)){
                $this->msg('error','删除失败');
                return false;
            }
        }
        return true;
    }

    /**
     * 下载文件
     * @param $filePath     目标文件的路劲
     * @param string $filename  下载时显示的名称
     * @return bool
     */
    public function fileDownload($filePath,$filename=''){
        if(empty($filePath)){
            $this->msg('error','缺少文件路劲');
            return false;
        }
        if (strpos($filePath,'.')!==0){
            $filePath='.'.$filePath;
        }

        if (is_file($filePath)) {
            $length = filesize($filePath);

            if ($filename){
                $ext=strrchr($filePath,'.');
                $showname = $filename.$ext;
            }else{
                $showname = ltrim(strrchr($filePath, '/'), '/');
            }
            $realpath =realpath($filePath);
            header("Content-Description: File Transfer");
            header('Content-type: application/octet-stream');
            header('Content-Length:' . $length);
            if (preg_match('/MSIE/', $_SERVER['HTTP_USER_AGENT'])) { //for IE
                header('Content-Disposition: attachment; filename="' . rawurlencode($showname) . '"');
            } else {
                header('Content-Disposition: attachment; filename="' . $showname . '"');
            }
            header("X-Sendfile: $realpath");
            exit;
        } else {
            $this->msg('error','文件不存在!');
            return false;
        }
    }


    public function msg($status,$info,$other=[]){
        $arr=['status'=>$status,'info'=>$info];
        if ($other){
            $arr['other']=$other;
        }
        return $this->msg = $arr;
    }
}

注意:

$upload = new \org\Upload();

这是就是一个上传文件的约束类你完全可以用$_FILES来获取上传文件信息

我把文件整个分享出来:网盘下载

下载整个文件后 \org\Upload() 参数的使用:

扫描二维码关注公众号,回复: 1690336 查看本文章
/**
     * 默认上传配置
     * @var array
     */
    private $config = [
        // 允许上传的文件MiMe类型
        'mimes'        => [],
        // 上传的文件大小限制 (0-不做限制)
        'maxSize'      => 0,
        // 允许上传的文件后缀
        'exts'         => [],
        // 自动子目录保存文件
        'autoSub'      => true,
        // 子目录创建方式,[0]-函数名,[1]-参数,多个参数使用数组
        'subName'      => ['date', 'Y-m-d'],
        //保存根路径
        'rootPath'     => './Uploads/',
        // 保存路径
        'savePath'     => '',
        // 上传文件命名规则,[0]-函数名,[1]-参数,多个参数使用数组
        'saveName'     => ['uniqid', ''],
        // 文件保存后缀,空则使用原后缀
        'saveExt'      => '',
        // 存在同名是否覆盖
        'replace'      => false,
        // 是否生成hash编码
        'hash'         => true,
        // 检测文件是否存在回调,如果存在返回文件信息数组
        'callback'     => false,
        // 文件上传驱动e,
        'driver'       => '',
        // 上传驱动配置
        'driverConfig' => [],
    ];

猜你喜欢

转载自blog.csdn.net/qq_36308324/article/details/78604638