ImageController.php 12.7 KB
<?php

namespace App\Http\Controllers\File;

use App\Enums\Common\Code;
use App\Http\Controllers\Controller;
use App\Http\Controllers\type;
use App\Models\File\Image as ImageModel;
use App\Models\Project\Project;
use App\Services\CosService;
use App\Services\TencentCosService;
use Illuminate\Http\Exceptions\HttpResponseException;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\Cache;
use Intervention\Image\Facades\Image;

class ImageController extends Controller
{
    public $path = '/upload';//路径

    public $config = '';//存储默认配置

    public $request = '';//request

    public $param = '';//参数

    public $token = '';//token

    public $cache = '';//缓存数据

    public $page = 1;

    public $row = 20;

    public $map = [];


    public $upload_location = 1;//是否同步到cos
    //上传图片类型
    public $image_type = [
        1 => 'image_product',
        2 => 'image_news',
        3 => 'image_blog',
        4 => 'image_product_icon',
        5 => 'image_product_cate',
        0 => 'image_other',
    ];

    public function __construct()
    {
        $this->request = request();
        $this->param = $this->request->all();
        $this->config = config('filesystems.disks.upload');
        $this->uploads = config('upload.default_image');
        $this->get_param();
    }

    /**
     * @remark :参数过滤
     * @name   :get_param
     * @author :lyh
     * @method :post
     * @time   :2023/8/14 14:27
     */
    public function get_param(){
        $param = $this->param;
        if(!empty($param)){
            foreach ($param as $k => $v){
                if(is_array($v)){
                    continue;
                }
                switch ($k){
                    case "order":
                        $this->order = $v;
                        break;
                    case 'page':
                        $this->page = $v;
                        break;
                    case 'row':
                        $this->row = $v;
                        break;
                    case "status":
                        $this->map['status'] = $v;
                        break;
                    default:
                        $this->map[$k] = $v;
                        break;
                }
            }
        }
    }
    /**
     * @name   :index
     * @author :lyh
     * @method :post
     * @time   :2023/5/11 17:19
     */
    public function index($hash = '', $w = 0 ,$h = 0 ){
        if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) || isset($_SERVER['HTTP_IF_NONE_MATCH'])) {
            header("HTTP/1.1 304 Not Modified");
            exit;
        }
        $imageModel = new ImageModel();
        $info = $imageModel->read(['hash'=>$hash]);
        if ($info === false) {
            $this->response('指定图片不存在!', Code::USER_ERROR);
        }
        //查看缩略图是否存在
        $filename = $this->config['root'] . '/' .$info['path'] . '_' . $w . '_' . $h;
        if(is_file($filename)){
            $content = file_get_contents($filename);
            $header['Content-Length'] = strlen($content);
        }else{
            $content = $this->readImageContent($info,$w,$h);
            $header['Content-Length'] = strlen($content);
        }
        $header['Content-Type'] = $info['mime'];
        return response($content,200,$header);
    }

    /**
     * @remark :缩略图不存在时获取图片
     * @name   :readImageContent
     * @author :lyh
     * @method :post
     * @time   :2023/7/27 9:26
     */
    public function readImageContent($info,$w,$h)
    {
        $path = $this->config['root'] . '/' . $info['path'];
        if (!is_file($path)) {
            $this->response('指定图片已被系统删除!', Code::USER_ERROR);
        }
        if ($w > 0 && $h > 0) {
            $path = $this->cacheImage($info, $w, $h);
            $content = file_get_contents($path);
        } else {
            $content = file_get_contents($path);
        }
        return $content;
    }
    /**
     * @name   :(图片上传)upload
     * @author :lyh
     * @method :post
     * @time   :2023/6/17 16:28
     */
    public function upload() {
        $this->request->validate([
            'image'=>['required'],
        ],[
            'image.required'=>'图片必须填写',
        ]);
        $files = $this->request->file('image');
        if (empty($files)) {
            $this->response('没有上传的文件!', Code::USER_ERROR);
        }
        $type = $this->request->post('type','single');
        $this->setUrl();
        if ($type == 'multi') {
            return $this->multi($files);
        }else{
            $size = $files->getSize();
            $image_type = $files->getClientOriginalExtension();
            $mime = $files->getMimeType();
            return $this->single($files,$size,$image_type,$mime);
        }
    }

    /**
     * @param $files
     * @remark :单图片上传
     * @name   :single
     * @author :lyh
     * @method :post
     * @time   :2023/6/17 16:30
     */
    public function single(&$files,$size,$image_type,$mime){
        $hash = hash_file('md5', $files->getPathname());
        //查看文件是否存在
        $imageModel = new ImageModel();
        $image_hash = $imageModel->read(['hash'=>$hash,'refer'=>$this->param['refer'] ?? 0]);
        if($image_hash !== false){
            return $this->response('图片资源',Code::SUCCESS,$this->responseData($image_hash['path']));
        }
        $url = $this->config['root'].$this->path;
        $fileName = uniqid().rand(10000,99999).'.'.$image_type;
        //上传到cos
        if($this->upload_location == 1){
            $cosService = new CosService();
            $cosService->uploadFile($files,$this->path,$fileName);
        }else{
            $res =  $files->move($url,$fileName);
            if ($res === false) {
                return $this->response($files->getError(), Code::USER_ERROR);
            }
        }
        $this->saveMysql($imageModel,$size,$image_type,$fileName,$hash,$this->upload_location,$mime);
        return $this->response('图片资源',Code::SUCCESS,$this->responseData($this->path.'/'.$fileName));
    }

    /**
     * @remark :保存数据库
     * @name   :saveMysql
     * @author :lyh
     * @method :post
     * @time   :2023/7/19 16:38
     */
    public function saveMysql(&$imageModel,$size,$image_type,$fileName,$hash,$is_cos = 0,$mime = ''){
        $data = [
            'path' => $this->path.'/'.$fileName,
            'created_at' => date('Y-m-d H:i:s',time()),
            'size' => $size,
            'hash' => $hash,
            'type'=>$image_type,
            'refer'=>$this->param['refer'] ?? 0,
            'is_cos'=>$is_cos,
            'mime'=>$mime,
            'project_id'=>$this->cache['project_id'] ?? 0,
        ];
        $rs = $imageModel->add($data);
        if ($rs === false) {
            return $this->response('添加失败', Code::USER_ERROR);
        }
        return true;
    }
    /**
     * @param $info
     * @param $w
     * @param $h
     * @remark :生成缩略图
     * @name   :cacheImage
     * @author :lyh
     * @method :post
     * @time   :2023/6/17 16:31
     */
    private function cacheImage($info, $w, $h) {
        $path = $info['path'];
        $filename = $this->config['root'] . '/' . $info['path'] . '_' . $w . '_' . $h;
        Image::make($path)->resize($w, $h)->save($filename);
        return $filename;
    }

    /**
     * @param $files
     * @remark :多图片上传
     * @name   :multi
     * @author :lyh
     * @method :post
     * @time   :2023/6/17 16:31
     */
    private function multi(&$files) {
        $data = [];
        foreach ($files as $file) {
            $size = $file->getSize();
            $image_type = $file->getClientOriginalExtension();
            $mime = $file->getMimeType();
            $imageModel = new ImageModel();
            $hash = hash_file('md5', $file->getPathname());
            $image_hash = $imageModel->read(['hash'=>$hash,'refer'=>$this->param['refer'] ?? 0]);
            if($image_hash !== false){
                $data[] = $this->responseData($image_hash['path']);
                continue;
            }
            $url = $this->config['root'].$this->path;
            $fileName = uniqid().rand(10000,99999).'.'.$file->getClientOriginalExtension();
            //同步数据到cos
            if($this->upload_location == 1){
                $cosService = new CosService();
                $cosService->uploadFile($file,$this->path,$fileName);
            }else{
                $res = $file->move($url,$fileName);
                if ($res === false) {
                     $this->response($file->getError(), Code::USER_ERROR);
                }
            }
            //批量存储
            $this->saveMysql($imageModel,$size,$image_type,$fileName,$hash,$this->upload_location,$mime);
            $data[] = $this->responseData($this->path.'/'.$fileName);
        }
         $this->response('图片资源',Code::SUCCESS,$data);
    }

    /**
     * @param $filename
     * @remark :下载
     * @name   :download
     * @author :lyh
     * @method :post
     * @time   :2023/7/19 17:59
     */
    public function download(){
        $imageModel = new ImageModel();
        ;
        $info = $imageModel->read(['path' => '/'.str_replace_url($this->param['path'])]);
        if ($info === false) {
            $this->response('指定文件不存在!', Code::USER_ERROR);
        }
        if($info['is_cos'] == 1){
            $cos = new CosService();
            $fileUrl = $cos->getImageUrl($info['path']);
        }else{
            $fileUrl = $this->config['root'].$info['path'];
            if (!is_file($fileUrl)) {
                $this->response('指定图片已被系统删除!', Code::USER_ERROR);
            }
        }
        $fileName = basename($info['path']);  // 要保存的文件名
        // 设置响应头
        header('Content-Description: File Transfer');
        header('Content-Type: application/octet-stream');
        header('Content-Disposition: attachment; filename="' . $fileName . '"');
        // 下载文件
        readfile($fileUrl);
    }

    /**
     * @remark :统一返回
     * @name   :response
     * @author :lyh
     * @method :post
     * @time   :2023/7/19 17:59
     */
    public function response($msg = null,string $code = Code::SUCCESS,$data = [],$result_code = 200,$type = 'application/json'): JsonResponse
    {
        $code = Code::fromValue($code);
        $result = [
            'message' => $msg == ' ' ? $code->description : $msg,
            'code' => $code->value,
            'data' => $data,
        ];
        $this->header['Content-Type'] = $type;
        $response =  response($result,$result_code,$this->header);
        throw new HttpResponseException($response);
    }


    /**
     * @remark :获取所有图片
     * @name   :getImageList
     * @author :lyh
     * @method :post
     * @time   :2023/6/29 11:48
     */
    public function getImageList(){
        $imageModel = new ImageModel();
        $lists = $imageModel->lists($this->map,$this->page,$this->row);
        if(!empty($lists) && !empty($lists['list'])){
            foreach ($lists['list'] as $k => $v){
                $v['image_link'] = getImageUrl($v['hash']);
                $lists['list'][$k] = $v;
            }
        }
        $this->response('success',Code::SUCCESS,$lists);
    }

    /**
     * @remark :保存路径
     * @name   :setUrl
     * @author :lyh
     * @method :post
     * @time   :2023/7/18 15:36
     */
    public function setUrl(){
        //A端上传
        if(isset($this->param['refer_type']) && $this->param['refer_type'] == 1){
            $this->path = $this->uploads['path_a'].'/'.$this->image_type[$this->param['refer']].'/'.date('Y-m');
        }else{
            //B端上传
            $this->token = $this->request->header('token');
            $this->cache = Cache::get($this->token);
            if(!isset($this->param['upload_method'])){
                //根据项目上传标识区分上传到cos/本地
                $projectModel = new Project();
                $project_info = $projectModel->read(['id'=>$this->cache['project_id']],['project_location']);
                if ($project_info['project_location'] != 0) {//危险项目时 上传到本地
                    $this->upload_location = 0;//上传到cos
                }
            }
            $this->path = $this->uploads['path_b'].'/'.$this->cache['project_id'].'/'.$this->image_type[$this->param['refer']].'/'.date('Y-m');
        }
    }

    /**
     * @remark :统一返回参数处理
     * @name   :responseData
     * @author :lyh
     * @method :post
     * @time   :2023/7/26 13:41
     */
    public function responseData($path = ''){
        $data = [
            'image'=>$path,
            'image_link'=>getImageUrl($path),
        ];
        return $data;
    }

}