ThinkPHP图片裁剪上传插件by WuBin 武斌

本篇文档主要是记录本人在ThinkPHP开发过程中找不到一款比较合适的图片裁剪上传的插件,所以根据PHP+jQuery+html5实现图片选取裁剪上传(兼容手机上传)进行了修改,最终实现了效果。

本文是在ThinkPHP3.2下进行测试实现的,使用ThinkPHP自带的图片上传裁剪库。其他环境没有测试。

本文件的前端可以通过以下链接下载ThinkPHP图片裁剪前端,提取密码hak8

ThnkPHP基本设置

首先在ThinkPHP中新建控制器和对应的模版文件,我是在Application下的Home应用下的Test控制器下。

Test控制器

<?php
namespace Home\Controller;
use Think\Controller;

class TestController extends HomeController{
	public function index(){
   	$this->display();
	}

public function picture_upload(){
    $data['rootPath']       =   './Uploads/';
    $data['savePath_raw']   =   'picture/raw/';
    $data['savePath_crop']  =   'picture/crop/';
    $data['savePath_thumb'] =   'picture/thumb/';
    $data['image_x']    =   $_POST['x1'];
    $data['image_y']    =   $_POST['y1'];
    $data['image_w']    =   $_POST['w'];
    $data['image_h']    =   $_POST['h'];
    exit(D('PublicUpload')->upload_advanced($data));
	}
}

index方法用来显示模版文件,即上传效果,参考素材火演示。 picture_upload用来接收从模板文件传过来的变量并且调用PublicUpload模型的upload_advanced方法来实现文件的上传。之所以使用是因为我讲图片的地址都传到了数据库,如果不传到数据库的话修改下面的upload_advanced到Test控制器也可以实现。 # 前段模版 <!DOCTYPE html> <html> <head> ThinkPHP图片截取上传 </head> <body>

        <div class="container">
            <div class="demo">
                <!-- <form id="upload_form" enctype="multipart/form-data" method="post" action="__PUBLIC__/libs/image_crop/upload.php" onsubmit="return checkForm()"> -->
                <form id="upload_form" enctype="multipart/form-data" method="post" action="{:U('Home/Test/picture_upload')}" onsubmit="return checkForm()">
                    <!-- hidden crop params -->
                    <input type="hidden" id="x1" name="x1" autocomplete="off" />
                    <input type="hidden" id="y1" name="y1" autocomplete="off"/>
                    <input type="hidden" id="x2" name="x2" autocomplete="off" />
                    <input type="hidden" id="y2" name="y2" autocomplete="off" />


                    <input type="file" name="file" id="image_file" onchange="fileSelectHandler()" />

                    <div class="error">注意:上传前,先截图</div>
                    <div class="step2">
                        <img id="preview" />
                            <div class="info">
                                <ul>
                                    <li><label>文件大小</label> <input type="text" id="filesize" name="filesize" class="input" autocomplete="off" /></li>
                                    <li><label>类型</label> <input type="text" id="filetype" name="filetype" class="input"autocomplete="off"/></li>
                                    <li><label>图像尺寸</label> <input type="text" id="filedim" name="filedim" class="input"autocomplete="off"/></li>
                                    <li><label>宽度</label> <input type="text" id="w" name="w" class="input"autocomplete="off"/></li>
                                    <li><label>高度</label> <input type="text" id="h" name="h" class="input"autocomplete="off"/></li>
                                </ul>
                            </div>
                        <input type="submit" value="上传" class="btn" />
                    </div>
                </form>
            </div>
        </div>
        <script type="text/javascript" src="__PUBLIC__/libs/image_crop/js/jquery.min.js"></script>
        <script src="__PUBLIC__/libs/image_crop/js/jquery.Jcrop.min.js"></script>
        <script src="__PUBLIC__/libs/image_crop/js/script.js"></script>
    </body>
</html>

所有的样式文件和JS我都放到了根目录下的Public/libs/image_crop目录内,所以路径地址写的PUBLIC/libs/image_crop。Form的action路径写的{:U(‘Home/Test/picture_upload’)}就是Test控制器的picture_upload方法。

后端upload_advanced方法

public function upload_advanced($data){
        //返回标准数据
        $return = array('error' => 0);
        $dir = I('post.dir'); //上传类型image、flash、media、file
		//根据上传文件类型改变上传大小限制
        $upload_config = C('UPLOAD_CONFIG');
        $upload_driver = C('UPLOAD_DRIVER');
        if(!$upload_driver){
            $return['error'] = 1;
            $return['message'] = '无效的文件上传驱动';
            return json_encode($return);
        }

        if($dir == 'image'){
            $upload_config['maxSize'] = C('UPLOAD_IMAGE_SIZE')*1024*1024; //图片的上传大小限制
        }else{
            $upload_config['maxSize'] = C('UPLOAD_FILE_SIZE')*1024*1024; //普通文件上传大小限制
        }

        //上传配置
        $ext_arr = array(
            'image' => array('gif', 'jpg', 'jpeg', 'png', 'bmp'),
            'flash' => array('swf', 'flv'),
            'media' => array('swf', 'flv', 'mp3', 'wav', 'wma', 'wmv', 'mid', 'avi', 'mpg', 'asf', 'rm', 'rmvb', 'mp4'),
            'file'  => array('doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx', 'pdf', 'wps', 'txt', 'zip', 'rar', 'gz', 'bz2', '7z'),
        );

        //计算文件散列以查看是否已有相同文件上传过
        $con['md5']  = md5_file($_FILES['file']['tmp_name']);
        $con['sha1'] = sha1_file($_FILES['file']['tmp_name']);
        $con['size'] = $_FILES['file']['size'];
        $upload = $this->where($con)->find();
        if($upload){ //发现相同文件直接返回
            $return['id']   = $upload['id'];
            $return['name'] = $upload['name'];
            $return['url']  = $upload['real_path'];
        }else{
            //上传文件
            $upload_config['removeTrash'] = array($this, 'removeTrash');
            $upload = new \Think\Upload($upload_config, $upload_driver, C("Ï{$upload_driver}_CONFIG")); //实例化上传类
            $upload->exts = $ext_arr[$dir]; //设置附件上传允许的类型
            $upload->rootPath = $data['rootPath'];
            $upload->savePath = $data['savePath_raw'];
            $info = $upload->upload($_FILES); //上传文件
            //图片裁剪、生成缩略图
            $image = new \Think\Image();
            $image_raw = './Uploads/' . $info['file']['savepath'] . $info['file']['savename'];
            $crop_path = $data['rootPath'].$data['savePath_crop'].date('Y-m-d',time()).'/';
            if(!is_dir($crop_path)){
                mkdir($crop_path, 0755, true);
            }
            $thumb_path = $data['rootPath'].$data['savePath_thumb'].date('Y-m-d',time()).'/';
            if(!is_dir($thumb_path)){
                mkdir($thumb_path, 0755, true);
            }
            $image -> open($image_raw);
            $image->crop($data['image_w'], $data['image_h'],$data['image_x'],$data['image_y'])->save($crop_path.$info['file']['savename']);
            $image->thumb(300, 300)->save($thumb_path.$info['file']['savename']);
            if(!$info){
                $return['error'] = 1;
                $return['message']  = '上传出错'.$upload->getError();
            }else{
                //获取上传数据
                $info = $info['file'];
                $upload_data['type'] = $info["type"];
                $upload_data['name'] = $info["name"];
                $upload_data['path'] = trim($crop_path,'.') . $info['savename'];
                $upload_data['raw']  = '/Uploads/' . $info['savepath'] . $info['savename'];
                $upload_data['thumb'] = trim($thumb_path,'.') . $info['savename'];
                $upload_data['url'] = $info["url"] ? : '';
                $upload_data['ext'] = $info["ext"];
                $upload_data['size'] = $info["size"];
                $upload_data['md5']  = $info['md5'];
                $upload_data['sha1']  = $info['sha1'];
                $upload_data['location']  = $upload_driver;

                $result = $this->create($upload_data);
                $result = $this->add($result);
                if($result){
                    if($info["url"]){
                        $return['url'] = $upload_data['url'];
                    }else{
                        $return['url'] = __ROOT__ . $upload_data['path'];
                    }
                    $return['name'] = $upload_data['name'];
                    $return['id'] = $result;
                }else{
                    $return['error'] = 1;
                    $return['message'] = '上传出错'.$this->error;
                }
            }
        }
        return json_encode($return);
}

最后返回JSON格式结果,方便前段调用。 上传的所有配置统统写在了config文件内,通过C方法配置。

//文件上传默认驱动
'UPLOAD_DRIVER' => 'Local',

//文件上传相关配置
'UPLOAD_CONFIG' => array(
    'mimes'    => '', //允许上传的文件MiMe类型
    'maxSize'  => 2*1024*1024, //上传的文件大小限制 (0-不做限制,默认为2M,后台配置会覆盖此值)
    'autoSub'  => true, //自动子目录保存文件
    'subName'  => array('date', 'Y-m-d'), //子目录创建方式,[0]-函数名,[1]-参数,多个参数使用数组
    'rootPath' => './Uploads/', //保存根路径
    'savePath' => '', //保存路径
    'saveName' => array('uniqid', ''), //上传文件命名规则,[0]-函数名,[1]-参数,多个参数使用数组
    'saveExt'  => '', //文件保存后缀,空则使用原后缀
    'replace'  => false, //存在同名是否覆盖
    'hash'     => true, //是否生成hash编码
    'callback' => false, //检测文件是否存在回调函数,如果存在返回文件信息数组
),

有不合适的地方还希望可以给出修改意见。

Published 10 November 2015