<?php
// +----------------------------------------------------------------------
// | 海豚PHP框架 [ DolphinPHP ]
// +----------------------------------------------------------------------
// | 版权所有 2016~2017 河源市卓锐科技有限公司 [ http://www.zrthink.com ]
// +----------------------------------------------------------------------
// | 官方网站: http://dolphinphp.com
// +----------------------------------------------------------------------
// | 开源协议 ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
namespace plugins\QiNiu;
use app\common\controller\Plugin;
use app\admin\model\Attachment as AttachmentModel;
use think\Db;
use think\Image;
use Qiniu\Auth;
use Qiniu\Storage\UploadManager;
use think\facade\Env;
require Env::get('root_path') . 'plugins/QiNiu/SDK/autoload.php';
/**
* 七牛上传插件
* @package plugins\QiNiu
* @author 蔡伟明 <314013107@qq.com>
*/
class QiNiu extends Plugin
{
/**
* @var array 插件信息
*/
public $info = [
// 插件名[必填]
'name' => 'QiNiu',
// 插件标题[必填]
'title' => '七牛上传插件',
// 插件唯一标识[必填],格式:插件名.开发者标识.plugin
'identifier' => 'qi_niu.ming.plugin',
// 插件图标[选填]
'icon' => 'fa fa-fw fa-upload',
// 插件描述[选填]
'description' => '仅支持DolphinPHP1.0.6以上版本,安装后,需将【<a href="/admin.php/admin/system/index/group/upload.html">上传驱动</a>】将其设置为“七牛云”。在附件管理中删除文件,并不会同时删除七牛云上的文件。',
// 插件作者[必填]
'author' => '蔡伟明',
// 作者主页[选填]
'author_url' => 'http://www.caiweiming.com',
// 插件版本[必填],格式采用三段式:主版本号.次版本号.修订版本号
'version' => '1.1.0',
// 是否有后台管理功能[选填]
'admin' => '0',
];
/**
* @var array 插件钩子
*/
public $hooks = [
'upload_attachment'
];
/**
* 上传附件
* @param array $params 参数
* @return mixed
* @author 蔡伟明 <314013107@qq.com>
*/
public function uploadAttachment($params = [])
{
$file = $params['file'];
// 缩略图参数
$thumb = request()->post('thumb', '');
// 水印参数
$watermark = request()->post('watermark', '');
$config = $this->getConfigValue();
$error_msg = '';
if ($config['ak'] == '') {
$error_msg = '未填写七牛【AccessKey】';
} elseif ($config['sk'] == '') {
$error_msg = '未填写七牛【SecretKey】';
} elseif ($config['bucket'] == '') {
$error_msg = '未填写七牛【Bucket】';
} elseif ($config['domain'] == '') {
$error_msg = '未填写七牛【Domain】';
}
if ($error_msg != '') {
switch ($params['from']) {
case 'wangeditor':
return "error|{$error_msg}";
break;
case 'ueditor':
return json(['state' => $error_msg]);
break;
case 'editormd':
return json(["success" => 0, "message" => $error_msg]);
break;
case 'ckeditor':
return ck_js(request()->get('CKEditorFuncNum'), '', $error_msg);
break;
default:
return json([
'code' => 0,
'class' => 'danger',
'info' => $error_msg
]);
}
}
$config['domain'] = rtrim($config['domain'], '/') . '/';
// 移动到框架应用根目录/uploads/ 目录下
$info = $file->move(config('upload_path') . DIRECTORY_SEPARATOR . 'temp', '');
// 文件信息
$file_info = $file->getInfo();
// 要上传文件的本地路径
$filePath = $info->getPathname();
// 上传到七牛后保存的文件名
$file_name = explode('.', $file_info['name']);
$ext = end($file_name);
$key = $info->hash('md5') . '.' . $ext;
// 如果是图片,则获取宽度和高度,并判断是否添加水印
$ext_limit = config('upload_image_ext');
$ext_limit = $ext_limit == '' ? [] : explode(',', $ext_limit);
// 缩略图路径
$thumb_path_name = '';
if (preg_grep("/$ext/i", $ext_limit)) {
$img = Image::open($info);
$img_width = $img->width();
$img_height = $img->height();
// 水印功能
if ($watermark == '') {
if (config('upload_thumb_water') == 1 && config('upload_thumb_water_pic') > 0) {
$this->create_water($info->getRealPath(), config('upload_thumb_water_pic'));
}
} else {
if (strtolower($watermark) != 'close') {
list($watermark_img, $watermark_pos, $watermark_alpha) = explode('|', $watermark);
$this->create_water($info->getRealPath(), $watermark_img, $watermark_pos, $watermark_alpha);
}
}
// 生成缩略图
if ($thumb == '') {
if (config('upload_image_thumb') != '') {
list($thumb_max_width, $thumb_max_height) = explode(',', config('upload_image_thumb'));
$thumb_path_name = $config['domain'] . $key . '?imageMogr2/thumbnail/' . $thumb_max_width . 'x' . $thumb_max_height;
}
} else {
if (strtolower($thumb) != 'close') {
list($thumb_size, $thumb_type) = explode('|', $thumb);
list($thumb_max_width, $thumb_max_height) = explode(',', $thumb_size);
$thumb_path_name = $config['domain'] . $key . '?imageMogr2/thumbnail/' . $thumb_max_width . 'x' . $thumb_max_height;
}
}
} else {
$img_width = '';
$img_height = '';
}
// 需要填写你的 Access Key 和 Secret Key
$accessKey = $config['ak'];
$secretKey = $config['sk'];
// 构建鉴权对象
$auth = new Auth($accessKey, $secretKey);
// 要上传的空间
$bucket = $config['bucket'];
// 生成上传 Token
$token = $auth->uploadToken($bucket, $key);
// 初始化 UploadManager 对象并进行文件的上传
$uploadMgr = new UploadManager();
// 调用 UploadManager 的 putFile 方法进行文件的上传
list($ret, $err) = $uploadMgr->putFile($token, $key, $filePath);
if ($err !== null) {
return json(['code' => 0, 'class' => 'danger', 'info' => '上传失败:' . $err]);
} else {
// 获取附件信息
$data = [
'uid' => session('user_auth.uid'),
'name' => $file_info['name'],
'mime' => $file_info['type'],
'path' => $config['domain'] . $key . '?v=' . rand(111111, 999999),
'ext' => $info->getExtension(),
'size' => $info->getSize(),
'md5' => $info->hash('md5'),
'sha1' => $info->hash('sha1'),
'thumb' => $thumb_path_name,
'module' => $params['module'],
'driver' => 'qiniu',
'width' => $img_width,
'height' => $img_height,
];
if ($file_add = AttachmentModel::create($data)) {
unset($info);
// 删除本地临时文件
@unlink(config('upload_path') . DIRECTORY_SEPARATOR . 'temp' . DIRECTORY_SEPARATOR . $file_info['name']);
// 返回结果
switch ($params['from']) {
case 'wangeditor':
return $data['path'];
break;
case 'ueditor':
return json([
"state" => "SUCCESS", // 上传状态,上传成功时必须返回"SUCCESS"
"url" => $data['path'], // 返回的地址
"title" => $file_info['name'], // 附件名
]);
break;
case 'editormd':
return json([
"success" => 1,
"message" => '上传成功',
"url" => $data['path'],
]);
break;
case 'ckeditor':
return ck_js(request()->get('CKEditorFuncNum'), $data['path']);
break;
default:
return json([
'code' => 1,
'info' => '上传成功',
'class' => 'success',
'id' => $file_add['id'],
'path' => $data['path']
]);
}
} else {
switch ($params['from']) {
case 'wangeditor':
return "error|上传失败";
break;
case 'ueditor':
return json(['state' => '上传失败']);
break;
case 'editormd':
return json(["success" => 0, "message" => '上传失败']);
break;
case 'ckeditor':
return ck_js(request()->get('CKEditorFuncNum'), '', '上传失败');
break;
default:
return json(['code' => 0, 'class' => 'danger', 'info' => '上传失败']);
}
}
}
}
/**
* 添加水印
* @param string $file 要添加水印的文件路径
* @param string $watermark_img 水印图片id
* @param string $watermark_pos 水印位置
* @param string $watermark_alpha 水印透明度
* @author 蔡伟明 <314013107@qq.com>
*/
private function create_water($file = '', $watermark_img = '', $watermark_pos = '', $watermark_alpha = '')
{
$img = Db::name('admin_attachment')->where('id', $watermark_img)->find();
$path = $img['path'];
$tmp = false;
if (strtolower(substr($path, 0, 4)) == 'http') {
$file_watermark = file_get_contents($path);
$thumb_water_pic = config('upload_path') . DIRECTORY_SEPARATOR . 'temp/' . $img['md5'] . '.' . $img['ext'];
if (false === file_put_contents($thumb_water_pic, $file_watermark)) {
return;
}
$tmp = true;
} else {
$thumb_water_pic = realpath(Env::get('root_path') . 'public/' . $path);
}
if (is_file($thumb_water_pic)) {
// 读取图片
$image = Image::open($file);
// 添加水印
$watermark_pos = $watermark_pos == '' ? config('upload_thumb_water_position') : $watermark_pos;
$watermark_alpha = $watermark_alpha == '' ? config('upload_thumb_water_alpha') : $watermark_alpha;
$image->water($thumb_water_pic, $watermark_pos, $watermark_alpha);
// 保存水印图片,覆盖原图
$image->save($file);
// 删除临时文件
if ($tmp) {
unlink($thumb_water_pic);
}
}
}
/**
* 安装方法
* @return bool
* @author 蔡伟明 <314013107@qq.com>
*/
public function install()
{
if (!version_compare(config('dolphin.product_version'), '1.0.6', '>=')) {
$this->error = '本插件仅支持DolphinPHP1.0.6或以上版本';
return false;
}
$upload_driver = Db::name('admin_config')->where(['name' => 'upload_driver', 'group' => 'upload'])->find();
if (!$upload_driver) {
$this->error = '未找到【上传驱动】配置,请确认DolphinPHP版本是否为1.0.6以上';
return false;
}
$options = parse_attr($upload_driver['options']);
if (isset($options['qiniu'])) {
$this->error = '已存在名为【qiniu】的上传驱动';
return false;
}
$upload_driver['options'] .= PHP_EOL . 'qiniu:七牛云';
$result = Db::name('admin_config')
->where(['name' => 'upload_driver', 'group' => 'upload'])
->setField('options', $upload_driver['options']);
if (false === $result) {
$this->error = '上传驱动设置失败';
return false;
}
return true;
}
/**
* 卸载方法
* @return bool
* @author 蔡伟明 <314013107@qq.com>
*/
public function uninstall()
{
$upload_driver = Db::name('admin_config')->where(['name' => 'upload_driver', 'group' => 'upload'])->find();
if ($upload_driver) {
$options = parse_attr($upload_driver['options']);
if (isset($options['qiniu'])) {
unset($options['qiniu']);
}
$options = implode_attr($options);
$result = Db::name('admin_config')
->where(['name' => 'upload_driver', 'group' => 'upload'])
->update(['options' => $options, 'value' => 'local']);
if (false === $result) {
$this->error = '上传驱动设置失败';
return false;
}
}
return true;
}
/**
* 前台 api 上传到七牛云
* $params 数组 file 本地图片地址 file_name 图片名称,uid,操作人
* @return array
*/
public function qiuNiu($params)
{
$config = $this->getConfigValue();
// 要上传文件的本地路径
$filePath = $params['file'];
// 上传到七牛后保存的文件名
$file_name = explode('.', $params['file_name']);
$ext = end($file_name);
$key = md5($filePath) . '.' . $ext;
// 如果是图片,则获取宽度和高度,并判断是否添加水印
$ext_limit = config('upload_image_ext');
$ext_limit = $ext_limit == '' ? [] : explode(',', $ext_limit);
// 需要填写你的 Access Key 和 Secret Key
$accessKey = $config['ak'];
$secretKey = $config['sk'];
// 构建鉴权对象
$auth = new Auth($accessKey, $secretKey);
// 要上传的空间
$bucket = $config['bucket'];
// 生成上传 Token
$token = $auth->uploadToken($bucket, $key);
// 初始化 UploadManager 对象并进行文件的上传
$uploadMgr = new UploadManager();
// 调用 UploadManager 的 putFile 方法进行文件的上传
list($ret, $err) = $uploadMgr->putFile($token, $key, $filePath);
if ($err !== null) {
return json(['code' => 0, 'class' => 'danger', 'info' => '上传失败:' . $err]);
} else {
// 获取附件信息
$data = [
'uid' =>$params['uid'],
'name' => $file_name,
'mime' => 'image/jpeg',
'path' => $config['domain'] . $key . '?v=' . rand(111111, 999999),
'ext' => 'jpeg',
'module' => 'api',
'driver' => 'qiniu',
];
if ($file_add = AttachmentModel::create($data)) {
unset($info);
// 删除本地临时文件
@unlink($filePath);
// 返回结果
$arr= array(
'code' => 1,
'info' => '上传成功',
'class' => 'success',
'id' => $file_add['id'],
'path' => $data['path']
);
return $arr;
} else {
$arr= array(
'code' => 0,
'info' => '上传失败',
'class' => 'errcode',
);
return $arr;
}
}
}
}
//处理图片,及合成
// 获取旅游详情分享图合成
public function getTourismShareImage($id)
{
$tourismModel = new TravelGoods();
$tourism = $tourismModel::getTourism($id);
// 线路二维码图片
$tourism['share_qrcode'] = $this->getTourismShareQrcode($id);
// 分享图片
$tourism['share_img'] = ImageResource::getImageUrl($tourism['share_img']);
if (!$tourism['share_img']) {
throw new TourismCollectionException(
[
'msg' => '没有找到指定的旅游线路分享图片',
'errorCode' => 40100
]
);
}
$a = $this->gdPicSynthesis($tourism['share_qrcode'],$tourism['share_img'],$id);
return $a;
}
//图片合成
private function gdPicSynthesis($share_qrcode,$share_img,$id){
ob_start();
//两张图片合成方法
$bgimg = $share_img;
$bg_info = getimagesize($bgimg);
//获取图片的后缀
$bg_type = image_type_to_extension($bg_info[2], false);
//拼接图片资源句柄函数
$func = 'imagecreatefrom' . $bg_type;
//创建图片资源句柄
$bg_image = $func($bgimg);
$imageZ =imagecreatetruecolor(298, 447);
//copy部分图像并调整
imagecopyresized($imageZ, $bg_image,0, 0,0, 0,298, 447, $bg_info[0], $bg_info[1]);
//图2处理 二维码
$tu2 = $share_qrcode;
list($width, $height)=getimagesize($tu2);
$new=imagecreatetruecolor(150, 150);
$img=imagecreatefromjpeg($tu2);
//copy部分图像并调整
imagecopyresized($new, $img,0, 0,0, 0,150, 150, $width, $height);
//图像输出新图片、另存为
imagejpeg($new, "pic1.jpg");
imagedestroy($new);
imagedestroy($img);
$tu2 = './pic1.jpg';
$tu2_mark = getimagesize($tu2);
$tu2_type = image_type_to_extension($tu2_mark[2], false);
//创建图片资源句柄
$tu2_func = 'imagecreatefrom' . $tu2_type;
$tu2_image = $tu2_func($tu2);
//合并背景图+二维码
imagecopy($imageZ, $tu2_image, 145, 295, 0, 0, 150, 150);
//图片输出函数拼接
$outFunc = 'image' . $bg_type;
$file_name=time();
//保存图片
$img_name = config('upload_path') .'/'. $file_name . '.jpg';
$outFunc($imageZ, $img_name);
$params['file']=$img_name;
$params['uid']='0';
$params['file_name']=$file_name . '.jpg';
$qiNiu=new QiNiu();//上传到七牛云
$list=$qiNiu->qiuNiu($params);
return $list;
}
// 获取线路二维码图片url
private function getTourismShareQrcode($tourismId)
{
// 获取会员编码
// $memberCode = TokenService::getCurrentMemberCode();
$memberCode='f047cb42';
// 二维码参数
$scene = 'member_code=' . $memberCode . '&id=' . $tourismId;
// 生成邀请二维码
$response = $this->miniApp->app_code->getUnlimit($scene, [
'page' => 'pages/protail/protail',
'width' => 600,
]);
if ($response instanceof \EasyWeChat\Kernel\Http\StreamResponse) {
// 生成二维码图片,后面建议走OSS,暂时简单实现
$fileName = $response->save('./public/static/tourismShare/img');
}
// 拼接可以访问的二维码url地址
return Config::get('base.qrcode_prefix') . 'public/static/tourismShare/img/' . $fileName;
}