zoukankan      html  css  js  c++  java
  • ThinkPHP5上传图片并压缩为缩略图

    使用thinkphp开发app后端中,需要实现一个处理上传图片队列的功能

    这是个上传多图片保存并且需要对其中一张图片进行压缩的功能
    (使用的html5 mui框架开发app,如果直接载入原图,app客户端列表中图稍微多几张就会使得webview十分卡顿,建议在开发中,一定要对用户上传的图片进行服务器端的压缩)

    之前已经写过一篇关入如何使用html5+的uploader上传多张图片到服务器的博客:
    http://www.cnblogs.com/devilyouwei/p/6790255.html
    并且实现了在前端进行压缩的功能(这是第一次压缩,有用户手机端进行)

    上传到服务器后我们还需对图片进行处理,我这里使用的php作为后端语言,框架为thinkphp5

    需要用到thinkphp的File类和Image类
    File类:前者获取到用户上传的file(文件)并进行路径和文件名的操作
    File类下的方法众多,主要有以下一些,使用之前应该先打印看一下,随意找一个文件测试一下效果,可以看的更加明白些:

    $file = new File(ROOT_PATH."/public/uploads/20170506/abc.jpg");
    $arr = [
    	'getATime' => $file->getATime(), //最后访问时间 
        'getBasename' => $file->getBasename(), //获取无路径的basename 
        'getCTime' => $file->getCTime(), //获取inode修改时间 
        'getExtension' => $file->getExtension(), //文件扩展名 
        'getFilename' => $file->getFilename(), //获取文件名 
        'getGroup' => $file->getGroup(), //获取文件组 
        'getInode' => $file->getInode(), //获取文件inode 
        'getLinkTarget' => $file->getLinkTarget(), //获取文件链接目标文件 
        'getMTime' => $file->getMTime(), //获取最后修改时间 
        'getOwner' => $file->getOwner(), //文件拥有者 
        'getPath' => $file->getPath(), //不带文件名的文件路径 
        'getPathInfo' => $file->getPathInfo(), //上级路径的SplFileInfo对象 
        'getPathname' => $file->getPathname(), //全路径 
        'getPerms' => $file->getPerms(), //文件权限 
        'getRealPath' => $file->getRealPath(), //文件绝对路径 
        'getSize' => $file->getSize(),//文件大小,单位字节 
        'getType' => $file->getType(),//文件类型 file dir link 
        'isDir' => $file->isDir(), //是否是目录 
        'isFile' => $file->isFile(), //是否是文件 
        'isLink' => $file->isLink(), //是否是快捷链接 
        'isExecutable' => $file->isExecutable(), //是否可执行 
        'isReadable' => $file->isReadable(), //是否可读 
        'isWritable' => $file->isWritable()  //是否可写 
        ];
    
    print_r($arr);
    return false;
    
    

    print_r打印到浏览器后:

    Array
    (
        [getATime] => 1494041766
        [getBasename] => abc.jpg
        [getCTime] => 1494041766
        [getExtension] => jpg
        [getFilename] => abc.jpg
        [getGroup] => 0
        [getInode] => 0
        [getLinkTarget] => D:wampwwwdashenpublicuploads20170506abc.jpg
        [getMTime] => 1494041766
        [getOwner] => 0
        [getPath] => D:wampwwwdashen/public/uploads/20170506
        [getPathInfo] => SplFileInfo Object
            (
                [pathName:SplFileInfo:private] => D:wampwwwdashen/public/uploads/20170506
                [fileName:SplFileInfo:private] => 20170506
            )
    
        [getPathname] => D:wampwwwdashen/public/uploads/20170506/abc.jpg
        [getPerms] => 33206
        [getRealPath] => D:wampwwwdashenpublicuploads20170506abc.jpg
        [getSize] => 571800
        [getType] => file
        [isDir] => 
        [isFile] => 1
        [isLink] => 
        [isExecutable] => 
        [isReadable] => 1
        [isWritable] => 1
    )
    

    关于如何用thinkphp5处理上传的多张图片文件,专门写一个private方法来处理,最后返回处理好的图片的路径的数组
    图片处理包括:

    1. 将用户上传的图片保存到public/uploads/目录下
    2. 按照日期建立目录,md5的编码时间作为文件名
    3. 压缩其中第一张图片为缩略图,专门用于预览(也要保存到数据库)
    4. 返回所有处理过图片的路径数组,由调用者处理后保存数据库

    代码:

    
     // 用户提交疑难
        public function addQues() {
            // 验证登陆session
            if (!session("?user_info"))
                return ['info'=>'登录状态失效', 'login'=>0];
    
            $ajax['title_id'] = input('post.title_id/d');
            $ajax['content'] = input('post.content/s');
            $ajax['star'] = input("post.star/s");
            $ajax['reward'] = input('post.reward/s');
            $ajax['message'] = input('post.message/s');
            $ajax['price'] = input('post.price/f');
    
            if($ajax['reward']!="金钱悬赏")
                $ajax['price'] = 0;
    
            if ($ajax['title_id'] == null || $ajax['content'] == null || $ajax['star'] == null || $ajax['reward'] == null)
                return ['info'=>'标题,内容,难度,悬赏方式不能为空', 'status'=>0];
    
            if ($ajax['title_id'] == 0 || $ajax['content'] == "" || $ajax['star'] == "" || $ajax['reward'] == "")
                return ['info'=>'标题,内容,难度,悬赏方式不能为空', 'status'=>0];
    
            // 上传图片
            $ajax['uid'] = session("user_info")['id'];
            $ajax['create_time'] = time();
            $ajax['update_time'] = $ajax['create_time'];
            $ajax['ip'] = get_client_ip();
            if (request()->file() != null) {
                $imgs = $this->upload();
    
                //根据imgs是否为数组鉴定是否有上传错误和超范围
                if(!is_array($imgs))
                    return['status'=>0,'info'=>$imgs];
    
                $ajax = array_merge($ajax, $imgs);
            }
            $ajax['is_del'] = 0;
            $ajax['is_effect'] = 1;
            $ajax['state'] = 0;
            $f = db("Ques")->insert($ajax);
            if ($f >= 1)
                return ['status'=>1, 'info'=>'需求单提交成功'];
            else
                return ['status'=>0, 'info'=>'数据插入失败'];
        }
    
    

    此方法中,压缩第一张图时需要用到原图的文件路径,名称等,我保存在原图同一目录下,在原图前面加上“thumb_”前缀作为区别。

    调用upload方法的控制器方法(外部方法):

    
        // 文件上传转储(多文件)
        // 暂且按照UNIX路径存储
        private function upload() {
            //创建的目录名称,日期(相对项目目录。用于数据库保存)
            $dirName = "public".DS."uploads".DS.(date('Ymd'));
            //创建保存目录(绝对路径。用于保存文件)
            $saveDir = ROOT_PATH.DS.$dirName;
    
            if (!file_exists($saveDir)){
                mkdir($saveDir);
            }
    
            $files = request()->file();//取得上传文件名
    
    
            foreach ( $files as $key => $file ) {
                // 自动生成文件名
                $info = $file->rule("get_rand")->validate(['ext'=>UPLOAD_EXT,'size'=>UPLOAD_SIZE])->move($saveDir,true,false);
    
                if ($info) {
                    //保存到数据的值
                    $data[$key] = $dirName .DS. $info->getFileName();
                } else {
                    return $file->getError();
                }
    
                // 压缩第一张图
                if ($key == 'img0') {
                    $image = Image::open($info->getRealPath());
                    // 保存
                    $thumbName = $saveDir.DS.$info->getFilename();
    
                    // 绝对路径加上文件名
                    $save = $saveDir.DS."thumb_" . $info->getFilename();
                    $image->thumb(300, 200, Image::THUMB_CENTER)->save($save);
    
                    $data['thumbnail'] = $dirName.DS.$thumbName;
                }
            }
            return $data;
        }
    }
    
    

    注意:thinkphp批量上传可能会出现同名文件覆盖的问题,因此我们重新规定了rule()方法使用的函数,在common.php写下一个随机生成函数,加上时间戳,这样重复的可能性就几乎为0了,极不易出现重名覆盖问题
    同名覆盖问题可能来源于上传文件并发的转储,时间太短了,因为php是秒级别的UNIX时间戳,导致了产生了相同的时间戳,从而用thinkphp官方的文档中的上传示例代码导致了重名覆盖问题

    //随机生成器
    function get_rand(){
        $now = $_SERVER['REQUEST_TIME'];//当前系统时间,比time()多5秒
        return rand().$now;
    }
    
  • 相关阅读:
    Java集合概述
    高可用性、负载均衡的mysql集群解决方案
    openOffice转换的时候乱码在linux下使用openOffice的时候发现在转换后出现了乱码
    (转)Linux安装SwfTools-0.9.2安装事,在执行make install时报错
    (转)java使用jsp servlet来防止csrf 攻击的实现方法
    (转)卫语句
    python的全局变量玩法还挺特别的
    那万恶的ssh真是麻烦
    关于有符号与无符号的字节
    开源而又强大的迷你型web服务器推荐
  • 原文地址:https://www.cnblogs.com/devilyouwei/p/6817649.html
Copyright © 2011-2022 走看看