ThinkPHP5上傳圖片並壓縮爲縮略圖

使用thinkphp開發app後端中,須要實現一個處理上傳圖片隊列的功能php

這是個上傳多圖片保存而且須要對其中一張圖片進行壓縮的功能
(使用的html5 mui框架開發app,若是直接載入原圖,app客戶端列表中圖稍微多幾張就會使得webview十分卡頓,建議在開發中,必定要對用戶上傳的圖片進行服務器端的壓縮)html

以前已經寫過一篇關入如何使用html5+的uploader上傳多張圖片到服務器的博客:
http://www.cnblogs.com/devilyouwei/p/6790255.html
而且實現了在前端進行壓縮的功能(這是第一次壓縮,有用戶手機端進行)前端

上傳到服務器後咱們還需對圖片進行處理,我這裏使用的php做爲後端語言,框架爲thinkphp5html5

須要用到thinkphp的File類和Image類
File類:前者獲取到用戶上傳的file(文件)並進行路徑和文件名的操做
File類下的方法衆多,主要有如下一些,使用以前應該先打印看一下,隨意找一個文件測試一下效果,能夠看的更加明白些:node

$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打印到瀏覽器後:web

Array
(
    [getATime] => 1494041766
    [getBasename] => abc.jpg
    [getCTime] => 1494041766
    [getExtension] => jpg
    [getFilename] => abc.jpg
    [getGroup] => 0
    [getInode] => 0
    [getLinkTarget] => D:\wamp\www\dashen\public\uploads\20170506\abc.jpg
    [getMTime] => 1494041766
    [getOwner] => 0
    [getPath] => D:\wamp\www\dashen\/public/uploads/20170506
    [getPathInfo] => SplFileInfo Object
        (
            [pathName:SplFileInfo:private] => D:\wamp\www\dashen\/public/uploads/20170506
            [fileName:SplFileInfo:private] => 20170506
        )

    [getPathname] => D:\wamp\www\dashen\/public/uploads/20170506/abc.jpg
    [getPerms] => 33206
    [getRealPath] => D:\wamp\www\dashen\public\uploads\20170506\abc.jpg
    [getSize] => 571800
    [getType] => file
    [isDir] => 
    [isFile] => 1
    [isLink] => 
    [isExecutable] => 
    [isReadable] => 1
    [isWritable] => 1
)

關於如何用thinkphp5處理上傳的多張圖片文件,專門寫一個private方法來處理,最後返回處理好的圖片的路徑的數組
圖片處理包括:ajax

  1. 將用戶上傳的圖片保存到public/uploads/目錄下
  2. 按照日期創建目錄,md5的編碼時間做爲文件名
  3. 壓縮其中第一張圖片爲縮略圖,專門用於預覽(也要保存到數據庫)
  4. 返回全部處理過圖片的路徑數組,由調用者處理後保存數據庫

代碼:thinkphp

// 用戶提交疑難
    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;
}
相關文章
相關標籤/搜索