• thinkphp文件上传以及图片处理


    文件上传

    上传表单

    在ThinkPHP中使用上传功能无需进行特别处理。例如,下面是一个带有附件上传的表单提交:

    <form action="__URL__/upload" enctype="multipart/form-data" method="post" >
    <input type="text" name="name" />
    <input type="file" name="photo" />
    <input type="submit" value="提交" >
    </form>
    

    注意,要使用上传功能 你的表单需要设置 enctype="multipart/form-data"

    多文件上传支持

    如果需要使用多个文件上传,只需要修改表单,把

    <input type='file'  name='photo'>
    

    改为

    <input type='file'  name='photo1'>
    <input type='file'  name='photo2'>
    <input type='file'  name='photo3'>
    

    或者

    <input type='file'  name='photo[]'>
    <input type='file'  name='photo[]'>
    <input type='file'  name='photo[]'>
    

    两种方式的多附件上传系统的文件上传类都可以自动识别。

    上传操作

    ThinkPHP文件上传操作使用ThinkUpload类,假设前面的表单提交到当前控制器的upload方法,我们来看下upload方法的实现代码:

    public function upload(){
        $upload = new ThinkUpload();// 实例化上传类
        $upload->maxSize   =     3145728 ;// 设置附件上传大小
        $upload->exts      =     array('jpg', 'gif', 'png', 'jpeg');// 设置附件上传类型
        $upload->rootPath  =     './Uploads/'; // 设置附件上传根目录
        $upload->savePath  =     ''; // 设置附件上传(子)目录
        // 上传文件 
        $info   =   $upload->upload();
        if(!$info) {// 上传错误提示错误信息
            $this->error($upload->getError());
        }else{// 上传成功
            $this->success('上传成功!');
        }
    }
    

    上传类对图片文件的上传安全做了支持,如果企图上传非法的图像文件,系统会提示 非法图像文件。 为了更好的使用上传功能,建议你的服务器开启finfo模块支持

    上传参数

    在上传操作之前,我们可以对上传的属性进行一些设置,Upload类支持的属性设置包括:

    属性描述
    maxSize 文件上传的最大文件大小(以字节为单位),0为不限大小
    rootPath 文件上传保存的根路径
    savePath 文件上传的保存路径(相对于根路径)
    saveName 上传文件的保存规则,支持数组和字符串方式定义
    saveExt 上传文件的保存后缀,不设置的话使用原文件后缀
    replace 存在同名文件是否是覆盖,默认为false
    exts 允许上传的文件后缀(留空为不限制),使用数组或者逗号分隔的字符串设置,默认为空
    mimes 允许上传的文件类型(留空为不限制),使用数组或者逗号分隔的字符串设置,默认为空
    autoSub 自动使用子目录保存上传文件 默认为true
    subName 子目录创建方式,采用数组或者字符串方式定义
    hash 是否生成文件的hash编码 默认为true
    callback 检测文件是否存在回调,如果存在返回文件信息数组

    上面的属性可以通过两种方式传入:

    实例化传入

    我们可以在实例化的时候直接传入参数数组,例如:

    $config = array(
        'maxSize'    =>    3145728,
        'rootPath'   =>    './Uploads/',
        'savePath'   =>    '',
        'saveName'   =>    array('uniqid',''),
        'exts'       =>    array('jpg', 'gif', 'png', 'jpeg'),
        'autoSub'    =>    true,
        'subName'    =>    array('date','Ymd'),
    );
    $upload = new ThinkUpload($config);// 实例化上传类
    

    关于saveName和subName的使用后面我们会有详细的描述。

    动态赋值

    支持在实例化后动态赋值上传参数,例如:

    $upload = new ThinkUpload();// 实例化上传类
    $upload->maxSize = 3145728;
    $upload->rootPath = './Uploads/';
    $upload->savePath = '';
    $upload->saveName = array('uniqid','');
    $upload->exts     = array('jpg', 'gif', 'png', 'jpeg');
    $upload->autoSub  = true;
    $upload->subName  = array('date','Ymd');
    

    上面的设置和实例化传入的效果是一致的。

    上传文件信息

    设置好上传的参数后,就可以调用ThinkUpload类的upload方法进行附件上传,如果失败,返回false,并且用getError方法获取错误提示信息;如果上传成功,就返回成功上传的文件信息数组。

    $upload = new ThinkUpload();// 实例化上传类
    $upload->maxSize   =     3145728 ;// 设置附件上传大小
    $upload->exts      =     array('jpg', 'gif', 'png', 'jpeg');// 设置附件上传类型
    $upload->rootPath  =      './Uploads/'; // 设置附件上传根目录
    $upload->savePath  =      ''; // 设置附件上传(子)目录
    // 上传文件 
    $info   =   $upload->upload();
    if(!$info) {// 上传错误提示错误信息
        $this->error($upload->getError());
    }else{// 上传成功 获取上传文件信息
        foreach($info as $file){
            echo $file['savepath'].$file['savename'];
        }
    }
    

    每个文件信息又是一个记录了下面信息的数组,包括:

    属性描述
    key 附件上传的表单名称
    savepath 上传文件的保存路径
    name 上传文件的原始名称
    savename 上传文件的保存名称
    size 上传文件的大小
    type 上传文件的MIME类型
    ext 上传文件的后缀类型
    md5 上传文件的md5哈希验证字符串 仅当hash设置开启后有效
    sha1 上传文件的sha1哈希验证字符串 仅当hash设置开启后有效

    文件上传成功后,就可以使用这些文件信息来进行其他的数据操作,例如保存到当前数据表或者单独的附件数据表。

    例如,下面表示把上传信息保存到数据表的字段:

    $model = M('Photo');
    // 取得成功上传的文件信息
    $info = $upload->upload();
    // 保存当前数据对象
    $data['photo'] = $info['photo']['savename'];
    $data['create_time'] = NOW_TIME;
    $model->add($data);
    

    单文件上传

    upload方法支持多文件上传,有时候,我们只需要上传一个文件,就可以使用Upload类提供的uploadOne方法上传单个文件,例如:

    public function upload(){
        $upload = new ThinkUpload();// 实例化上传类
        $upload->maxSize   =     3145728 ;// 设置附件上传大小
        $upload->exts      =     array('jpg', 'gif', 'png', 'jpeg');// 设置附件上传类型
        $upload->rootPath  =      './Uploads/'; // 设置附件上传根目录
        // 上传单个文件 
        $info   =   $upload->uploadOne($_FILES['photo1']);
        if(!$info) {// 上传错误提示错误信息
            $this->error($upload->getError());
        }else{// 上传成功 获取上传文件信息
             echo $info['savepath'].$info['savename'];
        }
    }
    

    uploadOne方法上传成功后返回的文件信息和upload方法的区别是只有单个文件信息的一维数组。

    上传文件的命名规则

    上传文件的命名规则(saveName)用于确保文件不会产生冲突或者覆盖的情况。命名规则的定义可以根据你的业务逻辑来调整,不是固定的。例如,如果你采用时间戳的方式来定义命名规范,那么在同时上传多个文件的时候可能产生冲突(因为同一秒内可以上传多个文件),因此你需要根据你的业务需求来设置合适的上传命名规则。这里顺便来说下saveName参数的具体用法。

    采用函数方式

    如果传入的字符串是一个函数名,那么表示采用函数动态生成上传文件名(不包括文件后缀),例如:

    // 采用时间戳命名
    $upload->saveName = 'time';
    // 采用GUID序列命名
    $upload->saveName = 'com_create_guid'; 
    

    也可以采用用户自定义函数

    // 采用自定义函数命名
    $upload->saveName = 'myfun'; 
    

    默认的命名规则设置是采用uniqid函数生成一个唯一的字符串序列。

    saveName的值支持数组和字符串两种方式,如果是只有一个参数或者没有参数的函数,直接使用字符串设置即可,如果需要传入额外的参数,可以使用数组方式,例如:

    // 采用date函数生成命名规则 传入Y-m-d参数
    $upload->saveName = array('date','Y-m-d'); 
    // 如果有多个参数需要传入的话 可以使用数组
    $upload->saveName = array('myFun',array('__FILE__','val1','val2'));
    

    如果需要使用上传的原始文件名,可以采用**FILE**传入,所以上面的定义规则,最终的结果是 myFun('上传文件名','val1','val2')执行的结果。

    直接设置上传文件名

    如果传入的参数不是一个函数名,那么就会直接当做是上传文件名,例如:

    $upload->saveName = time().'_'.mt_rand();
    

    表示上传的文件命名采用时间戳加一个随机数的组合字符串方式。

    当然,如果觉得有必要,你还可以固定设置一个上传文件的命名规则,用于固定保存某个上传文件。

    $upload->saveName = 'ThinkPHP';
    

    保持上传文件名不变

    如果你想保持上传的文件名不变,那么只需要设置命名规范为空即可,例如:

    $upload->saveName = '';
    

    一般来说不建议保持不变,因为会导致相同的文件名上传后被覆盖的情况。

    子目录保存

    saveName只是用于设置文件的保存规则,不涉及到目录,如果希望对上传的文件分子目录保存,可以设置autoSubsubName参数来完成,例如:

    // 开启子目录保存 并以日期(格式为Ymd)为子目录
    $upload->autoSub = true;
    $upload->subName = array('date','Ymd');
    

    可以使用自定义函数来保存,例如:

    // 开启子目录保存 并调用自定义函数get_user_id生成子目录
    $upload->autoSub = true;
    $upload->subName = 'get_user_id';
    

    和saveName参数一样,subName的定义可以采用数组和字符串的方式。

    注意:如果get_user_id函数未定义的话,会直接以get_user_id字符串作为子目录的名称保存。

    子目录保存和文件命名规则可以结合使用。

    上传驱动

    上传类可以支持不同的环境,通过相应的上传驱动来解决,默认情况下使用本地(Local)上传驱动,当然,你还可以设置当前默认的上传驱动类型,例如:

    'FILE_UPLOAD_TYPE'    =>    'Ftp',
    'UPLOAD_TYPE_CONFIG'  =>    array(        
            'host'     => '192.168.1.200', //服务器
            'port'     => 21, //端口
            'timeout'  => 90, //超时时间
            'username' => 'ftp_user', //用户名
            'password' => 'ftp_pwd', //密码 ),
    

    表示当前使用Ftp作为上传类的驱动,上传的文件会通过FTP传到指定的远程服务器。

    也可以在实例化上传类的时候指定,例如:

    $config = array(
        'maxSize'    =    3145728,
        'rootPath'   =    './Uploads/',
        'savePath'   =    '',
        'saveName'   =    array('uniqid',''),
        'exts'       =    array('jpg', 'gif', 'png', 'jpeg'),
        'autoSub'    =    true,
        'subName'    =    array('date','Ymd'),
    );
    $ftpConfig     =    array(        
            'host'     => '192.168.1.200', //服务器
            'port'     => 21, //端口
            'timeout'  => 90, //超时时间
            'username' => 'ftp_user', //用户名
            'password' => 'ftp_pwd', //密码 );
    
    $upload = new ThinkUpload($config,'Ftp',$ftpConfig);// 实例化上传类

    图像处理

    使用ThinkImage类进行图像处理功能,支持Gd库和Imagick库,包括对GIf图像处理的支持。

    实例化类库

    $image = new ThinkImage(); 
    

    默认使用GD库进行图像操作,如果需要使用Imagick库操作的话,需要改成:

    $image = new ThinkImage(ThinkImage::IMAGE_IMAGICK); 
    // 或者采用
    $image = new ThinkImage('Imagick'); 
    

    图像操作

    下面来看下基础的图像操作功能的使用方法。

    打开图像文件

    假设当前入口文件目录下面有一个1.jpg文件,如图所示:

    1

    使用open方法打开图像文件进行相关操作:

    $image = new ThinkImage(); 
    $image->open('./1.jpg');
    

    也可以简化成下面的方式:

    $image = new ThinkImage(ThinkImage::IMAGE_GD,'./1.jpg'); // GD库
    // 或者
    $image = new ThinkImage(ThinkImage::IMAGE_IMAGICK,'./1.jpg');  // imagick库
    

    获取图像信息

    可以获取打开图片的信息,包括图像大小、类型等,例如:

    $image = new ThinkImage(); 
    $image->open('./1.jpg');
    $width = $image->width(); // 返回图片的宽度
    $height = $image->height(); // 返回图片的高度
    $type = $image->type(); // 返回图片的类型
    $mime = $image->mime(); // 返回图片的mime类型
    $size = $image->size(); // 返回图片的尺寸数组 0 图片宽度 1 图片高度
    

    裁剪图片

    使用crop和save方法完成裁剪图片功能。

    $image = new ThinkImage(); 
    $image->open('./1.jpg');
    //将图片裁剪为400x400并保存为corp.jpg
    $image->crop(400, 400)->save('./crop.jpg');
    

    生成的图片如图:

    crop

    支持从某个坐标开始裁剪,例如下面从(100,30)开始裁剪:

    $image = new ThinkImage(); 
    $image->open('./1.jpg');
    //将图片裁剪为400x400并保存为corp.jpg
    $image->crop(400, 400,100,30)->save('./crop.jpg');
    

    生成的图片如图:

    crop

    生成缩略图

    使用thumb方法生成缩略图

    $image = new ThinkImage(); 
    $image->open('./1.jpg');
    // 按照原图的比例生成一个最大为150*150的缩略图并保存为thumb.jpg
    $image->thumb(150, 150)->save('./thumb.jpg');
    

    生成的缩略图如图所示:

    thumb

    我们看到实际生成的缩略图并不是150*150,因为默认采用原图等比例缩放的方式生成缩略图,最大宽度是150。

    可以支持其他类型的缩略图生成,设置包括ThinkImage的下列常量或者对应的数字:

    IMAGE_THUMB_SCALE     =   1 ; //等比例缩放类型
    IMAGE_THUMB_FILLED    =   2 ; //缩放后填充类型
    IMAGE_THUMB_CENTER    =   3 ; //居中裁剪类型
    IMAGE_THUMB_NORTHWEST =   4 ; //左上角裁剪类型
    IMAGE_THUMB_SOUTHEAST =   5 ; //右下角裁剪类型
    IMAGE_THUMB_FIXED     =   6 ; //固定尺寸缩放类型
    

    例如:

    居中裁剪

    $image = new ThinkImage(); 
    $image->open('./1.jpg');
    // 生成一个居中裁剪为150*150的缩略图并保存为thumb.jpg
    $image->thumb(150, 150,ThinkImage::IMAGE_THUMB_CENTER)->save('./thumb.jpg');
    

    居中裁剪后生成的缩略图效果如图:

    thumb

    左上角剪裁

    $image = new ThinkImage(); 
    $image->open('./1.jpg');
    // 生成一个左上角裁剪为150*150的缩略图并保存为thumb.jpg
    $image->thumb(150, 150,ThinkImage::IMAGE_THUMB_NORTHWEST)->save('./thumb.jpg');
    

    左上角裁剪后生成的缩略图效果如图:

    thumb

    缩放填充

    $image = new ThinkImage(); 
    $image->open('./1.jpg');
    // 生成一个缩放后填充大小150*150的缩略图并保存为thumb.jpg
    $image->thumb(150, 150,ThinkImage::IMAGE_THUMB_FILLED)->save('./thumb.jpg');
    

    缩放填充后生成的缩略图效果如图:

    thumb

    固定大小

    $image = new ThinkImage(); 
    $image->open('./1.jpg');
    // 生成一个固定大小为150*150的缩略图并保存为thumb.jpg
    $image->thumb(150, 150,ThinkImage::IMAGE_THUMB_FIXED)->save('./thumb.jpg');
    

    采用固定大小的缩略图可能会有所变形,生成的缩略图效果如图:

    thumb

    添加图片水印

    $image = new ThinkImage(); 
    $image->open('./1.jpg');
    //将图片裁剪为440x440并保存为corp.jpg
    $image->crop(440, 440)->save('./crop.jpg');
    // 给裁剪后的图片添加图片水印(水印文件位于./logo.png),位置为右下角,保存为water.gif
    $image->water('./logo.png')->save("water.gif");
    // 给原图添加水印并保存为water_o.gif(需要重新打开原图)
    $image->open('./1.jpg')->water('./logo.png')->save("water_o.gif"); 
    

    water方法的第二个参数表示水印的位置,可以传入下列ThinkImage类的常量或者对应的数字:

    IMAGE_WATER_NORTHWEST =   1 ; //左上角水印
    IMAGE_WATER_NORTH     =   2 ; //上居中水印
    IMAGE_WATER_NORTHEAST =   3 ; //右上角水印
    IMAGE_WATER_WEST      =   4 ; //左居中水印
    IMAGE_WATER_CENTER    =   5 ; //居中水印
    IMAGE_WATER_EAST      =   6 ; //右居中水印
    IMAGE_WATER_SOUTHWEST =   7 ; //左下角水印
    IMAGE_WATER_SOUTH     =   8 ; //下居中水印
    IMAGE_WATER_SOUTHEAST =   9 ; //右下角水印
    

    例如:

    $image = new ThinkImage(); 
    // 在图片左上角添加水印(水印文件位于./logo.png) 并保存为water.jpg
    $image->open('./1.jpg')->water('./logo.png',ThinkImage::IMAGE_WATER_NORTHWEST)->save("water.jpg"); 
    

    生成的图片效果如下:

    water

    还可以支持水印图片的透明度(0~100,默认值是80),例如:

    $image = new ThinkImage(); 
    // 在图片左上角添加水印(水印文件位于./logo.png) 水印图片的透明度为50 并保存为water.jpg
    $image->open('./1.jpg')->water('./logo.png',ThinkImage::IMAGE_WATER_NORTHWEST,50)->save("water.jpg"); 
    

    生成的效果如下:

    water

    也可以支持给图片添加文字水印(假设在入口文件的同级目录下存在1.ttf字体文件),例如:

    $image = new ThinkImage(); 
    // 在图片右下角添加水印文字 ThinkPHP 并保存为new.jpg
    $image->open('./1.jpg')->text('ThinkPHP','./1.ttf',20,'#000000',ThinkImage::IMAGE_WATER_SOUTHEAST)->save("new.jpg"); 
    

    生成的图片效果:

    new

    目前已经支持的上传驱动包括Local、Ftp、Sae、Bcs、七牛和又拍云等。

  • 相关阅读:
    Delphi SQL语句字符串拼接
    DELPHI的MEMO组件
    学习 SQL 语句
    Windows7系统目录迁移:Users,Progr…
    Delphi中Sender对象的知识
    Delphi处理事件函数中的Sender: TObject代表什么?
    (sender as TButton).some 和 TButton(sender).some 的区别是什么?
    什么情况下需要检测预装Win8/8.1电脑内置激活密钥(即Win8/8.1 OEM key)?
    用SQL语句查找包含有某个关键字的存储过程、触发器、函数等等
    DELPHI 解决DBGrid SHIFT键多选问题
  • 原文地址:https://www.cnblogs.com/ping04/p/8064072.html
Copyright © 2020-2023  润新知