当前位置: 首页 > news >正文

[FastAdmin] 上传图片并加水印,压缩图片

 1.app\common\library\Upload.php 文件

upload方法
    /**
     * 普通上传
     * @return \app\common\model\attachment|\think\Model
     * @throws UploadException
     */
    public function upload($savekey = null)
    {
        if (empty($this->file)) {
            throw new UploadException(__('No file upload or server upload limit exceeded'));
        }

        $this->checkSize();
        $this->checkExecutable();
        $this->checkMimetype();
        $this->checkImage();

        $savekey = $savekey ? $savekey : $this->getSavekey();
        $savekey = '/' . ltrim($savekey, '/');
        $uploadDir = substr($savekey, 0, strripos($savekey, '/') + 1);
        $fileName = substr($savekey, strripos($savekey, '/') + 1);

        $destDir = ROOT_PATH . 'public' . str_replace('/', DS, $uploadDir);
        $sha1 = $this->file->hash();

        //如果是合并文件
        if ($this->merging) {
            if (!$this->file->check()) {
                throw new UploadException($this->file->getError());
            }
            $destFile = $destDir . $fileName;
            $sourceFile = $this->file->getRealPath() ?: $this->file->getPathname();
            $info = $this->file->getInfo();
            $this->file = null;
            if (!is_dir($destDir)) {
                @mkdir($destDir, 0755, true);
            }
            rename($sourceFile, $destFile);
            $file = new File($destFile);
            $file->setSaveName($fileName)->setUploadInfo($info);
        } else {
            $file = $this->file->move($destDir, $fileName);
            if (!$file) {
                // 上传失败获取错误信息
                throw new UploadException($this->file->getError());
            }
        }
        $this->file = $file;
        $config=Db::name('config')->where(['group'=>'attachment'])->column('value','name');
        if ($config['open_watermark']){
            $fontPath = 'assets/fonts/zk.ttf'; // 确保字体文件路径正确,并且该字体支持中文
            $this->addTextWatermark('.'.$uploadDir . $file->getSaveName(), '.'.$uploadDir . $file->getSaveName(), $fontPath,$config);
        }
        //开启图片压缩
        if ($config['open_thum']){
            if (in_array($this->fileInfo['type'], ['image/gif', 'image/jpg', 'image/jpeg', 'image/bmp', 'image/png', 'image/webp']) || in_array($this->fileInfo['suffix'], ['gif', 'jpg', 'jpeg', 'bmp', 'png', 'webp'])) {
                $filesize=filesize('.'.$uploadDir . $file->getSaveName());
                if ($filesize>200000){
                    $this->compressImage('.'.$uploadDir . $file->getSaveName(),'.'.$uploadDir . $file->getSaveName(),$config['thum_quality']);
                    $imgInfo = getimagesize('.'.$uploadDir . $file->getSaveName());
                    $filesize=filesize('.'.$uploadDir . $file->getSaveName());
                    $this->fileInfo['size']=$filesize;
                    $this->fileInfo['imagewidth'] = $imgInfo[0] ?? 0;
                    $this->fileInfo['imageheight'] = $imgInfo[1] ?? 0;
                }
            }
        }
        $category = request()->post('category');
        $category = array_key_exists($category, config('site.attachmentcategory') ?? []) ? $category : '';
        $auth = Auth::instance();
        $params = array(
            'admin_id'    => (int)session('admin.id'),
            'user_id'     => (int)$auth->id,
            'filename'    => mb_substr(htmlspecialchars(strip_tags($this->fileInfo['name'])), 0, 100),
            'category'    => $category,
            'filesize'    => $this->fileInfo['size'],
            'imagewidth'  => $this->fileInfo['imagewidth'],
            'imageheight' => $this->fileInfo['imageheight'],
            'imagetype'   => $this->fileInfo['suffix'],
            'imageframes' => 0,
            'mimetype'    => $this->fileInfo['type'],
            'url'         => $uploadDir . $file->getSaveName(),
            'uploadtime'  => time(),
            'storage'     => 'local',
            'sha1'        => $sha1,
            'extparam'    => '',
        );
        $attachment = new Attachment();
        $attachment->data(array_filter($params));
        $attachment->save();

        \think\Hook::listen("upload_after", $attachment);
        return $attachment;
    }
    /**
     * 压缩图片
     * @param $sourcePath //需要压缩的图片
     * @param $targetPath //压缩后的图片
     * @param $quality //压缩质量
     * @return bool
     */
    public function compressImage($sourcePath, $targetPath, $quality) {
        $info = getimagesize($sourcePath);
        if ($info !== false) {
            $image = imagecreatefromstring(file_get_contents($sourcePath));
            imagejpeg($image, $targetPath, $quality); // 质量范围从0(差)到100(好)
            imagedestroy($image);
            return true;
        }
        return false;
    }
    /**
     * @param $imagePath 原图
     * @param $outputPath 输出图
     * @param $text 文字
     * @param $fontPath 字体路径
     * @param $fontSize 字体大小
     * @param $color 字体颜色
     * @param $position 位置
     * @return void
     */
    public function addTextWatermark($imagePath, $outputPath, $fontPath, $config) {
        // 创建图片资源
        $image = imagecreatefromstring(file_get_contents($imagePath));
        // 获取图片尺寸
        list($width, $height) = getimagesize($imagePath);
        // 设置文字颜色
        $black = imagecolorallocatealpha($image, 0, 0, 0, 100); // 最后一个参数是透明度,范围从0(完全透明)到127(完全不透明)
//        $textColor = imagecolorallocate($image, hexdec(substr($color, 0, 2)), hexdec(substr($color, 2, 2)), hexdec(substr($color, 4, 2)));
        // 设置字体路径和大小
        $font = realpath($fontPath);
        $fontSize=abs($config['watermark_size']);
        if (empty($config['watermark_colour'])) {
            $textColor =imagecolortransparent($image, $black);
        }else{
            $rgb=Checking::hColor2RGB($config['watermark_colour']);
            $black = imagecolorallocatealpha($image, $rgb['r'], $rgb['g'], $rgb['b'], 100); // 最后一个参数是透明度,范围从0(完全透明)到127(完全不透明)
            $textColor =imagecolortransparent($image, $black);
        }
        if (empty($config['watermark_text'])){
            $text='专用水印';
        }else{
            $text=$config['watermark_text'];
        }
        $bbox = imagettfbbox($fontSize, 0, $fontPath, $text); // 获取文字的边界框
        $text_width = $bbox[2] - $bbox[0];
        $text_height = $bbox[7] - $bbox[1];
        if (!empty($config['watermark_position'])) {
            if ($width-$text_width*3>50){
                $watermark_position=explode(',', $config['watermark_position']);
                foreach ($watermark_position as $position) {
                    switch ($position) {
                        case 1:
                            imagettftext($image, $fontSize, 0,  ($width - $text_width*3)/4 ,  $height/6 , $textColor, $font, $text);
                            break;
                        case 2:
                            imagettftext($image, $fontSize, 0,  ($width - $text_width*3)/4 ,  $height/6*3 , $textColor, $font, $text);
                            break;
                        case 3:
                            imagettftext($image, $fontSize, 0,  ($width - $text_width*3)/4 ,  $height/6*5 , $textColor, $font, $text);
                            break;
                        case 4:
                            imagettftext($image, $fontSize, 0,  ($width - $text_width*3)/4*2+$text_width,  $height/6 , $textColor, $font, $text);
                            break;
                        case 5:
                            imagettftext($image, $fontSize, 0,  ($width - $text_width*3)/4*2+$text_width,  $height/6*3 , $textColor, $font, $text);
                            break;
                        case 6:
                            imagettftext($image, $fontSize, 0,  ($width - $text_width*3)/4*2+$text_width,  $height/6*5 , $textColor, $font, $text);
                            break;
                        case 7:
                            imagettftext($image, $fontSize, 0,  ($width - $text_width*3)/4*3+$text_width*2,  $height/6 , $textColor, $font, $text);
                            break;
                        case 8:
                            imagettftext($image, $fontSize, 0,  ($width - $text_width*3)/4*3+$text_width*2,  $height/6*3 , $textColor, $font, $text);
                            break;
                        case 9:
                            imagettftext($image, $fontSize, 0,  ($width - $text_width*3)/4*3+$text_width*2,  $height/6*5 , $textColor, $font, $text);
                            break;
                    }
                }
            }
        }
        // 保存图片
        imagejpeg($image, $outputPath);
        imagedestroy($image);
    }
    /**
     * 颜色转换 16进制转rgb
     * @param $hexColor
     * @return array
     */
    public static function hColor2RGB($hexColor)
    {
        $color = str_replace('#', '', $hexColor);
        if (strlen($color) > 3) {
            $rgb = array(
                'r' => hexdec(substr($color, 0, 2)),
                'g' => hexdec(substr($color, 2, 2)),
                'b' => hexdec(substr($color, 4, 2))
            );
        } else {
            $color = str_replace('#', '', $hexColor);
            $r = substr($color, 0, 1) . substr($color, 0, 1);
            $g = substr($color, 1, 1) . substr($color, 1, 1);
            $b = substr($color, 2, 1) . substr($color, 2, 1);
            $rgb = array(
                'r' => hexdec($r),
                'g' => hexdec($g),
                'b' => hexdec($b)
            );
        }
        return $rgb;
    }

 数据库配置

颜色选择器添加,请参考之前的文章

【FastAdmin】在页面中使用layui,以此引申使用颜色选择器示例-CSDN博客

相关文章:

  • 重读《Java面试题,10万字208道Java经典面试题总结(附答案)》
  • 一种 SQL Server 数据库恢复方案:解密、恢复并导出 MDF/NDF/BAK文件
  • 【Elasticsearch】Mapping概述
  • 适用于iOS的应用商店优化(ASO)清单
  • Qt信号槽调用出错:Qt: Dead lock detected while activating a BlockingQueuedConnection
  • Anaconda 安装指南:Windows、macOS 和 Linux 的详细安装步骤
  • 轮子项目--消息队列的实现(3)
  • Redis初阶笔记
  • 【Linux】cron计划任务定时执行命令
  • 问界M8细节曝光,L3自动驾驶有了!
  • 【LeetCode】394. 字符串解码
  • Windows中指定路径安装DockerDesktop
  • 02、QLExpress从入门到放弃,相关API和文档
  • Electron:使用electron-react-boilerplate创建一个react + electron的项目
  • 回顾Golang的Channel与Select第一篇
  • Anaconda +Jupyter Notebook安装(2025最新版)
  • 【C】初阶数据结构5 -- 栈
  • 【Python爬虫(1)】专栏开篇:夯实Python基础
  • KVM虚拟化快速入门,最佳的开源可商用虚拟化平台
  • 详解Windows 系统上部署 Spring Boot + MyBatis + MySQL 项目
  • 李云泽:将尽快推出支持小微企业民营企业融资一揽子政策
  • 印度导弹凌晨打击巴基斯坦多座设施,巴总理:正对战争行为作有力回应
  • 巴基斯坦外交部:印度侵略行径侵犯巴主权
  • 短剧剧组在贵州拍戏突遇极端天气,演员背部、手臂被冰雹砸伤
  • 马斯克的胜利?OpenAI迫于压力放弃营利性转型计划
  • 今晚上海地铁多条线路加开定点加班车,2号线运营至次日2时