用户注册



邮箱:

密码:

用户登录


邮箱:

密码:
记住登录一个月忘记密码?

发表随想


还能输入:200字
云代码 - php代码库

大文件上传

2020-07-18 作者: 云代码会员举报

[php]代码库

<?php
function testLog($content)
{
    file_put_contents("a.txt",   var_export($content, true)."\r\n", FILE_APPEND);
}
/**
 * [helper 取值简便方法]
 * @param  [String] $query   [post.arg get.arg server.arg cookie.arg]
 * @param  [type] $default [默认值]
 * @return [type]          [description]
 */
function helper($query,$default=null){
    $qus = explode('.', $query);
    if(count($qus) === 1){
        $type = strtolower($_SERVER['REQUEST_METHOD']);
    }else{
        $type = strtolower($qus[0]);
        $query = $qus[1];
    }
    switch ($type) {
        case 'post':
            return isset($_POST[$query]) ? $_POST[$query] : $default;
        case 'get':
            return isset($_GET[$query]) ? $_GET[$query] : $default;
        case 'server':
            return isset($_SERVER[$query]) ? $_SERVER[$query] : $default;
        case 'cookie':
            return isset($_COOKIE[$query]) ? $_COOKIE[$query] : $default;
        default:
            return $default;
    }
}
date_default_timezone_set('PRC');
header('Content-type: application/json');
//上传文件
testLog($_FILES);
if ($_SERVER['REQUEST_METHOD'] === 'POST'){
 
    if (!empty($_FILES)){
        foreach ($_FILES as $file) {
            $uploader = new Uploader();
            $info = $uploader->upload($file);
            //目前块只包含一个文件
            echo json_encode($uploader->getResult());
            die;
        }
    }
}else if($_SERVER['REQUEST_METHOD'] === 'GET'){
    //断点上传
    //获取文件基本信息
    $uploader = new Uploader();
    $upload = $uploader->getUploadInfo();
    echo json_encode($upload);
}
 
 
 
 
 
/**
 * 分隔文件处理
 */
class Uploader{
 
    /**
     * 临时文件上传保存目录
     */
    const UPLOAD_TMP_PATH = './_tmp/';
    /**
     * 合并后的文件保存目录
     */
    const UPLOAD_REAL_PATH = './upload/';
 
    /**
     * 文件上传成功状态
     */
    const STATUS_SUCCESS = 0;
 
    /**
     * 文件上传失败状态
     */
    const STATUS_MOVE_ERROR = 1;
 
    /**
     * [$error 错误消息]
     * @var string
     */
    protected $error = '';
    /**
     * [$code 消息代码]
     * @var integer
     */
    protected $code = 0;
 
    /**
     * [
     * __construct 构造方法,主要获取上传的基本信息.和服务端的数据进行对比.
     * NOTE:可以结合文件的hash值实现文件秒传功能,原理差不多了
     * ]
     */
    public function __construct(){
        $this->config = array(
            'filename' => helper('filename'),
            'filesize' => intval(helper('filesize')),
            'filetype' => helper('filetype'),
            'modified' => intval(helper('modified')),
            'trunksize'=> intval(helper('trunksize'))
        );
        $this->hash = md5(serialize($this->config));
    }
 
    /**
     * [upload 上传文件]
     * @param  [type] $file [$_FILES[0]前端上传的FILE]
     * @return [type]       [description]
     */
    public function upload($file){
        // print_r($this->config);
        $trunk = intval(helper('post.trunk'));
        $total = helper('post.total');
        // print_r($file);
        //文件移动成功,记录文件上传指针
        $trunkname = self::UPLOAD_TMP_PATH . $this->hash . '.part.'.$trunk;
 
        if(@move_uploaded_file($file['tmp_name'], $trunkname)){
 
            static::log('success','文件'.$this->config['filename'].',块'.$trunk.'移动成功');
 
            $upload = $this->_uploadSuccess($trunk,$trunkname);
            if(count($upload) == $total){
                //合并文件
                $this->combineTrunkFile();
            }
             
            $this->setCode(self::STATUS_SUCCESS,'ok');
            return true;
        }
 
        static::log('error','文件'.$this->config['filename'].',块'.$trunk.'移动失败');
 
        $this->setCode(self::STATUS_MOVE_ERROR,'移动上传块'.$trunk.'失败');
        return false;
    }
 
    /**
     * [setCode 设置返回消息]
     * @param [type] $code [code]
     * @param string $msg  [消息]
     */
    protected function setCode($code,$msg=''){
        $this->error = $msg;
        $this->code = $code;
    }
 
    /**
     * [getResult 获取结果]
     * @return [type] [result]
     */
    public function getResult(){
        return [
            'code'  => $this->code,
            'error' => $this->error
        ];
    }
 
    /**
     * [_uploadSuccess 记录上传成功的块]
     * @param  [type] $trunk [块id]
     * @return [type]        [返回上传所有已经上传的块]
     */
    protected function _uploadSuccess($trunk,$trunkname){
 
        $log = self::UPLOAD_TMP_PATH .$this->hash.'.log';
 
        $uploadLog = $this->getUploadInfo();
 
 
        if(false === array_key_exists($trunk, $uploadLog['record'])
            || $uploadLog['record'][$trunk] < $uploadLog['trunksize']){
            $uploadLog['record'][ $trunk ] = filesize($trunkname);
            file_put_contents( $log,serialize($uploadLog) );
        }
 
        return $uploadLog['record'];
    }
 
    /**
     * [getUploadInfo 获取服务端保存的文件上传信息]
     * @return [type] [description]
     */
    public function getUploadInfo(){
        $log = self::UPLOAD_TMP_PATH .$this->hash.'.log';
 
        if(file_exists($log)){
            $uploadLog = unserialize(file_get_contents($log));
        }else{
            $uploadLog = $this->config;
            $uploadLog['total'] = helper('post.total',0);
            $uploadLog['record'] = [];
        }
 
        return $uploadLog;
    }
 
    /**
     * [combineTrunkFile 合并文件]
     * @param  [type] $config [文件碎片信息]
     * @return [type]         [description]
     */
    public function combineTrunkFile(){
        $config = $this->getUploadInfo();
 
        $partname = self::UPLOAD_TMP_PATH . $this->hash . '.part.';
 
        $fp = fopen(self::UPLOAD_REAL_PATH . $config['filename'], 'w');
        //注意,切割的文件编号从1开始的
        for ($i=1; $i <= $config['total']; $i++) {
            fwrite($fp, file_get_contents( $partname.$i ));
            //产出文件
            unlink($partname.$i);
        }
 
        static::log('success','文件'.$config['filename'].'合并成功');
 
        fclose($fp);
    }
 
    /**
     * [log 记录上传日志]
     * @param  string $type [description]
     * @param  string $msg  [description]
     * @return [type]       [description]
     */
    public static function log($type='', $msg=''){
        $str =  sprintf('[%s] %s => %s'.PHP_EOL,date('Y-m-d H:i:s'),strtoupper($type),$msg);
 
        if (($fp = fopen('upload_log.log', 'a+')) !== false) {
            fputs($fp, $str);
            fclose($fp);
        }
 
    }
 
 
}


网友评论    (发表评论)


发表评论:

评论须知:

  • 1、评论每次加2分,每天上限为30;
  • 2、请文明用语,共同创建干净的技术交流环境;
  • 3、若被发现提交非法信息,评论将会被删除,并且给予扣分处理,严重者给予封号处理;
  • 4、请勿发布广告信息或其他无关评论,否则将会删除评论并扣分,严重者给予封号处理。


扫码下载

加载中,请稍后...

输入口令后可复制整站源码

加载中,请稍后...