ad

不知道是不是个例,苹果CMS 2025.1000.4052版本。同步某些资源站图片死活下载不下来,查看同步出错的视频有几百条,强迫症的我自然无法接受,于是找原因,发现这批图片的后缀虽然是 .jpg,但实际文件头标识为 ftypavif,这是一种新兴的高性能图片格式 AVIF。虽然在浏览器能打开,大概是是苹果cms的图片验证机制认为他不是真正的图片或已经损坏,所以拒绝下载到本地。

考虑到现代浏览器(Chrome, Edge, Safari等)已经原生支持 AVIF 的显示,服务器端是否“认识”它并不影响前端展示。我采取了免检入库的策略:

核心修改: 修改 APPlication/common/model/Image.PHP 文件。

逻辑调整: 注释掉 down_exec 方法中针对 GETimagesize() 的严格类型检查。

修改后的代码如下:

<?php
namespace app\common\model;
use think\image\Exception;

class Image extends Base {

    public function down_load($URL, $config, $flag = 'vod')
    {
        if (substr($url, 0, 4) == 'http') {
            return $this->down_exec($url, $config, $flag);
        } else {
            return $url;
        }
    }

    public function down_exec($url, $config, $flag = 'vod')
    {
        $upload_image_ext = 'jpg,jpeg,png,gif,webp';
        $ext = strtolower(pathinfo($url, PATHINFO_EXTENSION));
        if (!in_array($ext, explode(',', $upload_image_ext))) {
            $ext = 'jpg';
        }
        $img = Mac_curl_get($url);
        if (empty($img) || strlen($img) < 10) {
            return $url . '#err';
        }
        $file_name = md5(uniqid()) .'.' . $ext;
        // 上传附件路径
        $_upload_path = ROOT_PATH . 'upload' . '/' . $flag . '/';
        // 附件访问路径
        $_save_path = 'upload'. '/' . $flag . '/' ;
        $ymd = date('Ymd');
        $n_dir = $ymd;
        for($i=1;$i<=100;$i++){
            $n_dir = $ymd .'-'.$i;
            $path1 = $_upload_path . $n_dir. '/';
            if(file_exists($path1)){
                $farr = glob($path1.'*.*');
                if($farr){
                    $fcount = count($farr);
                    if($fcount>999){
                        continue;
                    }
                    else{
                        break;
                    }
                }
                else{
                    break;
                }
            }
            else{
                break;
            }
        }

        $_upload_path .= $n_dir . '/';
        $_save_path .= $n_dir . '/';

        //附件访问地址
        $_file_path = $_save_path.$file_name;
        //写入文件
        $saved_img_path = $_upload_path . $file_name;
        $r = mac_write_file($saved_img_path, $img);
        if(!$r){
            return $url;
        }
        
        // --- 修改开始:放行无法识别的图片格式(如 AVIF) ---
        $image_info = @getimagesize($saved_img_path);
        $extension_hash = [
            '1'  => 'gif',
            '2'  => 'jpg',
            '3'  => 'png',
            '18' => 'webp',
        ];
        // 如果 GD 库无法获取信息(image_info 为空),不再报错返回 #err
        // 这样即使是 AVIF 格式也会被当作正常文件存入数据库
        if (!isset($image_info[2]) || !isset($extension_hash[$image_info[2]])) {
            // 保持静默,不返回 #err
        }
        // --- 修改结束 ---

        $file_size = filesize($_upload_path.$file_name);
        // 水印
        if ($config['watermark'] == 1) {
            $this->watermark($_file_path,$config,$flag);
        }
        // 缩略图
        if ($config['thumb'] == 1) {
            $this->makethumb($_file_path,$config,$flag);
        }
        //上传到远程
        $_file_path = model('Upload')->api($_file_path, $config);

        $tmp = $_file_path;
        if (str_starts_with($tmp, '/upload')) {
            $tmp = substr($tmp,1);
        }
        if (str_starts_with($tmp, 'upload')) {
            $annex = [];
            $annex['annex_file'] = $tmp;
            $annex['annex_type'] = 'image';
            $annex['annex_size'] = $file_size;
            model('Annex')->saveData($annex);
        }
        return $_file_path;
    }

    public function watermark($file_path,$config,$flag='vod')
    {
        if(empty($config['watermark_font'])){
            $config['watermark_font'] = './static/font/test.ttf';
        }
        try {
            $image = \think\Image::open('./' . $file_path);
            $image->text($config['watermark_content']."", $config['watermark_font'], $config['watermark_size'], $config['watermark_color'],$config['watermark_location'])->save('./' . $file_path);
        }
        catch(\Exception $e){

        }
    }

    public function makethumb($file_path,$config,$flag='vod',$new=1)
    {
        $thumb_type = $config['thumb_type'];
        $data['thumb'] = [];
        if (!empty($config['thumb_size'])) {
            try {
                $image = \think\Image::open('./' . $file_path);
                // 支持多种尺寸的缩略图
                $thumbs = explode(',', $config['thumb_size']);
                foreach ($thumbs as $k => $v) {
                    $t_size = explode('x', strtolower($v));
                    if (!isset($t_size[1])) {
                        $t_size[1] = $t_size[0];
                    }
                    $new_thumb = $file_path . '_' . $t_size[0] . 'x' . $t_size[1] . '.' . strtolower(pathinfo($file_path, PATHINFO_EXTENSION));
                    if($new==0){
                        $new_thumb = $file_path;
                    }
                    $image->thumb($t_size[0], $t_size[1], $thumb_type)->save('./' . $new_thumb);
                    $thumb_size = round(filesize('./' . $new_thumb) / 1024, 2);
                    $data['thumb'][$k]['type'] = 'image';
                    $data['thumb'][$k]['flag'] = $flag;
                    $data['thumb'][$k]['file'] = $new_thumb;
                    $data['thumb'][$k]['size'] = $thumb_size;
                    $data['thumb'][$k]['ctime'] = request()->time();

                    if ($config['watermark'] == 1) {// 开启文字水印
                        $image = \think\Image::open('./' . $new_thumb);
                        $image->text($config['watermark_content'], $config['watermark_font'], $config['watermark_size'], $config['watermark_color'])->save('./' . $new_thumb);
                    }
                }
            }
            catch(\Exception $e){

            }
        }
        return $data;
    }
}

实际上这样做会有多大风险会怎么样,(风险提示)比如下载伪装成图片的垃圾,千趣也不清楚,代码只提供参考.

qianqu
( 千趣源码网全面的综合平台 )
ad
ad
ad
ad
千趣源码