php动态生成海报图片、七牛云上传图片、七牛云打包文件
场景描述
具体业务中遇到了动态生成图片同时保存到七牛云上,然后打包提供下载的问题。
常规方案一般保存到服务器上,然后打包下载后删除就可以了,为了节约带宽和服务器资源,算是另辟蹊径了。
解决
逛了一逛github,最后使用了 kkokk/poster 的库,相当丝滑。 文档地址
public function generateCardImages()
{
$bgCanvas = '图片的地址';
$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(); // 输出图片流
}
首先要安装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(看文档是收费的,但是不贵)
依旧使用 qiniu/php-sdk 包来实现,注意新增的 use 部分
use Qiniu\Processing\PersistentFop;
// 加入消息队列
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
再记录一下
示例代码
/**
* @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];
}
(以上资料内容侵删) 转载时请告知(以上资料内容侵删) 每个人都知道的,哪怕已经很糟糕了但是努力生活依旧很重要。