php动态生成海报图片、七牛云上传图片、七牛云打包文件

发布时间 2023-10-19 11:03:00作者: 喝水自由

场景描述

具体业务中遇到了动态生成图片同时保存到七牛云上,然后打包提供下载的问题。

常规方案一般保存到服务器上,然后打包下载后删除就可以了,为了节约带宽和服务器资源,算是另辟蹊径了。

解决

1. 动态生成图片

逛了一逛github,最后使用了 kkokk/poster 的库,相当丝滑。  文档地址

public function generateCardImages()
    {
        $bgCanvas = 'C:\Users\31719\Desktop\bg.png';
        $poster = Poster::config([
            'path' => '图片的地址', // 设置图片保存地址、图片文件名、图片类型
        ])
            ->buildImDst($bgCanvas, 3189, 1914, [41, 43, 48, 1], false)
            ->buildText('苏轼', 400, 555, 100, [0, 0, 0, 1], 0, '', 10)
            ->buildText('男', 400, 695, 100, [0, 0, 0, 1], 0, '', 10)
            ->buildText('1704818834940', 400, 845, 100, [0, 0, 0, 1], 0, '', 10)
            ->buildQr('二维码的内容', ['center', 800], 'center', 0, 0, 1200, 1200, 20, 1) // 添加一个二维码上去
            ->baseData(); // 输出图片流
    }

 


 

2.base64流图片保存到七牛云上

首先要安装qiniu/php-sdk第三方包

composer require qiniu/php-sdk

<?php

namespace App\Services;

use Qiniu\Auth;

class CardService
{
    private $auth;

    public function __construct()
    {
        $accessKey = env('QINIU_ACCESS_KEY');
        $secretKey = env('QINIU_SECRET_KEY');
        $this->auth = new Auth($accessKey, $secretKey);
    }
    
    /**
     * 上传base64位图片到七牛云
     * $image base64位图片流
     */
    public function uploadPicBase64($image)
    {
        $bucket = env('QINIU_BUCKET');

        // 生成上传Token
        $upToken = $this->auth->uploadToken($bucket);
        $num = strpos($image, ',');
        $image = substr($image, $num + 1);
        $str = isset($image) ? $image : false;

        //生成图片key
        $name = 'a/b/' . uniqid(); //pic为存储空间的目录
        $Key = base64_encode($name);

        if ($str) {
            $qiniu = self::phpCurlImg("http://upload-z0.qiniu.com/putb64/-1/key/" . $Key, $str, $upToken);
            //upload.qiniup.com 上传域名适用于华东空间。华北空间使用 upload-z1.qiniu.com,华南空间使用 upload-z2.qiniu.com,北美空间使用 upload-na0.qiniu.com。

            $qiniuArr = json_decode($qiniu, true);
            if (!empty($qiniuArr['key']) && $qiniuArr['key'] == $name) {
                return env('QINIU_IMAGE_DOMAIN_2') . $qiniuArr['key']; //只会返回给你一个key,你需要将key和你的七牛云域名拼在一起就能访问
            } else {
                return false;
            }
        }
        return false;
    }

    //七牛base64上传方法
    public static function phpCurlImg($remote_server, $post_string, $upToken)
    {
        $headers = array();
        $headers[] = 'Content-Type:application/octet-stream';
        $headers[] = 'Authorization:UpToken ' . $upToken;
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $remote_server);
        curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $post_string);
        curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
        curl_setopt($ch, CURLOPT_TIMEOUT, 30);
        $data = curl_exec($ch);
        curl_close($ch);
        return $data;
    }
}

 


 

3.使用七牛云的多文件打包特性,打包成zip(看文档是收费的,但是不贵)

七牛云合并文件的文档说明

七牛云收费文档

// 加入消息队列
    public function job()
    {
        //七牛云压缩文件测试
        // 要压缩的文件所在的空间和文件名
        $bucket = env('QINIU_BUCKET');
        // 注意这个key 是你空间里现存的文件名称(只是名称 不需要完整的url地址 文件大小必须大于5kb以上)
        $key = 'a/b/652f96dd2d8ae';

        // 用户默认没有私有队列,需要在这里创建然后填写
        // https://portal.qiniu.com/dora/media-gate/pipeline 创建队列路径
        $pipeline = '需要去上面的地址里手动创建';

        $pfop = new PersistentFop($this->auth, null);

        // 进行 zip 压缩的 文件路径 完整的 url
        $url1 = '文件地址1';
        $url2 = '文件地址2';

        // 压缩后的 文件名称
        $zipKey = 'a/b/test123.zip';

        $fops = 'mkzip/2/url/' . base64_urlsafe_encode($url1);
        $fops .= '/url/' . base64_urlsafe_encode($url2);
        $fops .= '|saveas/' . base64_urlsafe_encode("$bucket:$zipKey");

        // 处理完成后通知到你的业务服务器(需要可以公网访问,并能够相应 200 OK)
        $notify_url = null;

        // 当转码后的文件名与源文件名相同时,是否覆盖源文件
        $force = false;

        list($id, $err) = $pfop->execute($bucket, $key, $fops, $pipeline, $notify_url, $force);

        echo "\n====> pfop mkzip result: \n";
        if ($err != null) {
            dump((array) $err);
        } else {
            echo "PersistentFop Id: $id\n";
        }

        // 查询转码的进度和状态
        list($ret, $err) = $pfop->status($id);
        echo "\n====> pfop mkzip status: \n";
        if ($err != null) {
            echo '---------';
            dump($err);
        } else {
            dump($ret);
        }
    }

附:

标准Base64不适合直接放在URL里传输,因为URL编码器会把标准Base64中的/+字符转义为%xx的形式

/**
 * base64 url安全编码
 */
public function base64_urlsafe_encode($data)
{
    return rtrim(strtr(base64_encode($data), '+/', '-_'), '=');
 }


/**
 * base64 url安全解码
 */
 public function base64_urlsafe_decode($data)
{
     return base64_decode(strtr($data, '-_', '+/'));
 }

避坑的点

这里的$key需要带上路径,否则会报错找不到文件;$pipeline需要手动创建

 

End

 


再记录一下

普通文件上传到七牛云上的demo

示例代码
/**
     * @param $file      接收文件上传的值 这里的file是$_FILES获取的
     * @return \think\response\Json
     */
    public static function normal_upload($file){

        if(!$file){
            return ['msg'=>'文件不能为空', 'code'=>201, 'data'=>''];
        }
        require_once ROOT_PATH. 'vendor/qiniu/php-sdk/autoload.php'; //引入加载文件

        //本地的文件路径
        $localFilePath = $file['file']['tmp_name'];

        //截取文件后缀名
        //$suffix = '.jpg';
        $suffix = strtolower(substr($file['file']['name'],strpos($file['file']['name'],'.')));
   
        //生成一个唯一的文件名称,重命名 (md5加密原文件名+秒+随机数)
        $fileName = md5($file['file']['name']) . date('s',time()) . rand(1,9999999);
        $fileName .= $suffix;

        //上传七牛云业务逻辑
        $accessKey = config('site.qiniu_accesskey'); //去控制台的秘钥管理拿AK
        $secretKey = config('site.qiniu_secretkey');//去控制台的秘钥管理拿SK
        $auth = new Auth($accessKey, $secretKey);
        //七牛云桶名,根据自己实际进行填写
        $bucket = config('site.qiniu_bucket');
        // 生成上传Token
        $token = $auth->uploadToken($bucket);
        // 构建 UploadManager 对象
        $uploadMgr = new UploadManager();

        // 调用 UploadManager 的 putFile 方法进行文件的上传。
        list($ret, $err) = $uploadMgr->putFile($token, $fileName, $localFilePath);

        //错误信息提示
        if ($err != null) {
            //可调整为错误页面
            return ['msg'=>'上传失败', 'code'=>201, 'data'=>''];
        }

        //把七牛云图片路径存储到我们自己的数据库  七牛云图片路径
        $imageUrl = config('site.qiniu_domain'). $fileName;

        return ['msg'=>'上传成功', 'code'=>200, 'data'=>$imageUrl];
    }