前言
将图片上传到阿里云OSS是一种趋势,一个必然。当你的项目图片过多,需要频繁上传和替换的时候,用阿里云OSS可以很方便的管理你的图片,节省服务器空间,大大提高了效率。阿里云OSS是阿里云提供的海量、安全、低成本、高可靠的云存储服务。你可以通过调用API,在任何应用、任何时间、任何地点上传和下载数据,也可以通过Web控制台对数据进行简单的管理。阿里云OSS适合存放任意类型的文件,适合各种网站、开发企业及开发者使用。
如果直接把图片上传到阿里云OSS是比较简单的,应该很多人都懂,但是用百度UEditor上传图片到阿里云OSS,就没那么简单了,所以我感觉还是有必要写这篇文章分享出来,给有需要的人。
效果图
修改百度UEditor的文件
1、修改这几个文件:
1.1、修改Uploader.class.php文件
注意:修改的部分我有加注释,注意看。
<?php
/**
* Created by JetBrains PhpStorm.
* User: taoqili
* Date: 12-7-18
* Time: 上午11: 32
* UEditor编辑器通用上传类
*/
class Uploader
{
private $fileField; //文件域名
private $file; //文件上传对象
private $base64; //文件上传对象
private $config; //配置信息
private $oriName; //原始文件名
private $fileName; //新文件名
private $fullName; //完整文件名,即从当前配置目录开始的URL
private $filePath; //完整文件名,即从当前配置目录开始的URL
private $fileSize; //文件大小
private $fileType; //文件类型
private $stateInfo; //上传状态信息,
private $stateMap = array( //上传状态映射表,国际化用户需考虑此处数据的国际化
"SUCCESS", //上传成功标记,在UEditor中内不可改变,否则flash判断会出错
"文件大小超出 upload_max_filesize 限制",
"文件大小超出 MAX_FILE_SIZE 限制",
"文件未被完整上传",
"没有文件被上传",
"上传文件为空",
"ERROR_TMP_FILE" => "临时文件错误",
"ERROR_TMP_FILE_NOT_FOUND" => "找不到临时文件",
"ERROR_SIZE_EXCEED" => "文件大小超出网站限制",
"ERROR_TYPE_NOT_ALLOWED" => "文件类型不允许",
"ERROR_CREATE_DIR" => "目录创建失败",
"ERROR_DIR_NOT_WRITEABLE" => "目录没有写权限",
"ERROR_FILE_MOVE" => "文件保存时出错",
"ERROR_FILE_NOT_FOUND" => "找不到上传文件",
"ERROR_WRITE_CONTENT" => "写入文件内容错误",
"ERROR_UNKNOWN" => "未知错误",
"ERROR_DEAD_LINK" => "链接不可用",
"ERROR_HTTP_LINK" => "链接不是http链接",
"ERROR_HTTP_CONTENTTYPE" => "链接contentType不正确"
);
/**
* 构造函数
* @param string $fileField 表单名称
* @param array $config 配置项
* @param bool $base64 是否解析base64编码,可省略。若开启,则$fileField代表的是base64编码的字符串表单名
*/
public function __construct($fileField, $config, $type = "upload")
{
$this->fileField = $fileField;
$this->config = $config;
$this->type = $type;
if ($type == "remote") {
$this->saveRemote();
} else if($type == "base64") {
$this->upBase64();
} else {
$this->upFile();
}
$this->stateMap['ERROR_TYPE_NOT_ALLOWED'] = iconv('unicode', 'utf-8', $this->stateMap['ERROR_TYPE_NOT_ALLOWED']);
}
/**
* 上传文件的主处理方法
* @return mixed
*/
private function upFile()
{
$file = $this->file = $_FILES[$this->fileField];
if (!$file) {
$this->stateInfo = $this->getStateInfo("ERROR_FILE_NOT_FOUND");
return;
}
if ($this->file['error']) {
$this->stateInfo = $this->getStateInfo($file['error']);
return;
} else if (!file_exists($file['tmp_name'])) {
$this->stateInfo = $this->getStateInfo("ERROR_TMP_FILE_NOT_FOUND");
return;
} else if (!is_uploaded_file($file['tmp_name'])) {
$this->stateInfo = $this->getStateInfo("ERROR_TMPFILE");
return;
}
//修改:上传阿里云OSS
$upload=new \source\core\widgets\upload\FileUpload();
$Pictureinfo=$upload->UploadUeditorPicture($file);
$this->oriName = $file['name'];
$this->fileSize = $file['size'];
$this->fileType = $this->getFileExt();
$this->fullName = '/'.$Pictureinfo['path'];
$this->filePath = $Pictureinfo['path'];
$this->fileName = $this->getFileName();
$dirname = dirname($this->filePath);
//检查文件大小是否超出限制
if (!$this->checkSize()) {
$this->stateInfo = $this->getStateInfo("ERROR_SIZE_EXCEED");
return;
}
//检查是否不允许的文件格式
if (!$this->checkType()) {
$this->stateInfo = $this->getStateInfo("ERROR_TYPE_NOT_ALLOWED");
return;
}
//创建目录失败
// if (!file_exists($dirname) && !mkdir($dirname, 0777, true)) {
// $this->stateInfo = $this->getStateInfo("ERROR_CREATE_DIR");
// return;
// } else if (!is_writeable($dirname)) {
// $this->stateInfo = $this->getStateInfo("ERROR_DIR_NOT_WRITEABLE");
// return;
// }
$this->stateInfo = $this->stateMap[0];
//移动文件
// if (!(move_uploaded_file($file["tmp_name"], $this->filePath) && file_exists($this->filePath))) { //移动失败
// $this->stateInfo = $this->getStateInfo("ERROR_FILE_MOVE");
// } else { //移动成功
// $this->stateInfo = $this->stateMap[0];
// }
}
/**
* 处理base64编码的图片上传
* @return mixed
*/
private function upBase64()
{
$base64Data = $_POST[$this->fileField];
$img = base64_decode($base64Data);
$this->oriName = $this->config['oriName'];
$this->fileSize = strlen($img);
$this->fileType = $this->getFileExt();
$this->fullName = $this->getFullName();
$this->filePath = $this->getFilePath();
$this->fileName = $this->getFileName();
$dirname = dirname($this->filePath);
//检查文件大小是否超出限制
if (!$this->checkSize()) {
$this->stateInfo = $this->getStateInfo("ERROR_SIZE_EXCEED");
return;
}
//创建目录失败
if (!file_exists($dirname) && !mkdir($dirname, 0777, true)) {
$this->stateInfo = $this->getStateInfo("ERROR_CREATE_DIR");
return;
} else if (!is_writeable($dirname)) {
$this->stateInfo = $this->getStateInfo("ERROR_DIR_NOT_WRITEABLE");
return;
}
//移动文件
if (!(file_put_contents($this->filePath, $img) && file_exists($this->filePath))) { //移动失败
$this->stateInfo = $this->getStateInfo("ERROR_WRITE_CONTENT");
} else { //移动成功
$this->stateInfo = $this->stateMap[0];
}
}
/**
* 拉取远程图片
* @return mixed
*/
private function saveRemote()
{
$imgUrl = htmlspecialchars($this->fileField);
$imgUrl = str_replace("&", "&", $imgUrl);
//http开头验证
if (strpos($imgUrl, "http") !== 0) {
$this->stateInfo = $this->getStateInfo("ERROR_HTTP_LINK");
return;
}
//获取请求头并检测死链
$heads = get_headers($imgUrl);
if (!(stristr($heads[0], "200") && stristr($heads[0], "OK"))) {
$this->stateInfo = $this->getStateInfo("ERROR_DEAD_LINK");
return;
}
//格式验证(扩展名验证和Content-Type验证)
$fileType = strtolower(strrchr($imgUrl, '.'));
if (!in_array($fileType, $this->config['allowFiles']) || stristr($heads['Content-Type'], "image")) {
$this->stateInfo = $this->getStateInfo("ERROR_HTTP_CONTENTTYPE");
return;
}
//打开输出缓冲区并获取远程图片
ob_start();
$context = stream_context_create(
array('http' => array(
'follow_location' => false // don't follow redirects
))
);
readfile($imgUrl, false, $context);
$img = ob_get_contents();
ob_end_clean();
preg_match("/[\/]([^\/]*)[\.]?[^\.\/]*$/", $imgUrl, $m);
$this->oriName = $m ? $m[1]:"";
$this->fileSize = strlen($img);
$this->fileType = $this->getFileExt();
$this->fullName = $this->getFullName();
$this->filePath = $this->getFilePath();
$this->fileName = $this->getFileName();
$dirname = dirname($this->filePath);
//检查文件大小是否超出限制
if (!$this->checkSize()) {
$this->stateInfo = $this->getStateInfo("ERROR_SIZE_EXCEED");
return;
}
//创建目录失败
if (!file_exists($dirname) && !mkdir($dirname, 0777, true)) {
$this->stateInfo = $this->getStateInfo("ERROR_CREATE_DIR");
return;
} else if (!is_writeable($dirname)) {
$this->stateInfo = $this->getStateInfo("ERROR_DIR_NOT_WRITEABLE");
return;
}
//移动文件
if (!(file_put_contents($this->filePath, $img) && file_exists($this->filePath))) { //移动失败
$this->stateInfo = $this->getStateInfo("ERROR_WRITE_CONTENT");
} else { //移动成功
$this->stateInfo = $this->stateMap[0];
}
}
/**
* 上传错误检查
* @param $errCode
* @return string
*/
private function getStateInfo($errCode)
{
return !$this->stateMap[$errCode] ? $this->stateMap["ERROR_UNKNOWN"] : $this->stateMap[$errCode];
}
/**
* 获取文件扩展名
* @return string
*/
private function getFileExt()
{
return strtolower(strrchr($this->oriName, '.'));
}
/**
* 重命名文件
* @return string
*/
private function getFullName()
{
//替换日期事件
$t = time();
$d = explode('-', date("Y-y-m-d-H-i-s"));
$format = $this->config["pathFormat"];
$format = str_replace("{yyyy}", $d[0], $format);
$format = str_replace("{yy}", $d[1], $format);
$format = str_replace("{mm}", $d[2], $format);
$format = str_replace("{dd}", $d[3], $format);
$format = str_replace("{hh}", $d[4], $format);
$format = str_replace("{ii}", $d[5], $format);
$format = str_replace("{ss}", $d[6], $format);
$format = str_replace("{time}", $t, $format);
//过滤文件名的非法自负,并替换文件名
$oriName = substr($this->oriName, 0, strrpos($this->oriName, '.'));
$oriName = preg_replace("/[\|\?\"\<\>\/\*\\\\]+/", '', $oriName);
$format = str_replace("{filename}", $oriName, $format);
//替换随机字符串
$randNum = rand(1, 10000000000) . rand(1, 10000000000);
if (preg_match("/\{rand\:([\d]*)\}/i", $format, $matches)) {
$format = preg_replace("/\{rand\:[\d]*\}/i", substr($randNum, 0, $matches[1]), $format);
}
$ext = $this->getFileExt();
return $format . $ext;
}
/**
* 获取文件名
* @return string
*/
private function getFileName () {
return substr($this->filePath, strrpos($this->filePath, '/') + 1);
}
/**
* 获取文件完整路径
* @return string
*/
private function getFilePath()
{
$fullname = $this->fullName;
// $rootPath = $_SERVER['DOCUMENT_ROOT'];
// if (substr($fullname, 0, 1) != '/') {
// $fullname = '/' . $fullname;
// }
//修改:替换路径
return $fullname;
}
/**
* 文件类型检测
* @return bool
*/
private function checkType()
{
return in_array($this->getFileExt(), $this->config["allowFiles"]);
}
/**
* 文件大小检测
* @return bool
*/
private function checkSize()
{
return $this->fileSize <= ($this->config["maxSize"]);
}
/**
* 获取当前上传成功文件的各项信息
* @return array
*/
public function getFileInfo()
{
return array(
"state" => $this->stateInfo,
"url" => $this->fullName,
"title" => $this->fileName,
"original" => $this->oriName,
"type" => $this->fileType,
"size" => $this->fileSize
);
}
}
1.2、修改config.json文件,这个文件主要是修改图片路径,改为你的阿里云OSS的路径
/* 前后端通信相关的配置,注释只允许使用多行方式 */
{
/* 上传图片配置项 */
"imageActionName": "uploadimage", /* 执行上传图片的action名称 */
"imageFieldName": "upfile", /* 提交的图片表单名称 */
"imageMaxSize": 2048000, /* 上传大小限制,单位B */
"imageAllowFiles": [".png", ".jpg", ".jpeg", ".gif", ".bmp"], /* 上传图片格式显示 */
"imageCompressEnable": true, /* 是否压缩图片,默认是true */
"imageCompressBorder": 1600, /* 图片压缩最长边限制 */
"imageInsertAlign": "none", /* 插入的图片浮动方式 */
"imageUrlPrefix": "http://test.oss-cn-hangzhou.aliyuncs.com", /* 图片访问路径前缀 */
"imagePathFormat": "data/attachment/image/{yyyy}{mm}{dd}/{time}{rand:6}", /* 上传保存路径,可以自定义保存路径和文件名格式 */
/* {filename} 会替换成原文件名,配置这项需要注意中文乱码问题 */
/* {rand:6} 会替换成随机数,后面的数字是随机数的位数 */
/* {time} 会替换成时间戳 */
/* {yyyy} 会替换成四位年份 */
/* {yy} 会替换成两位年份 */
/* {mm} 会替换成两位月份 */
/* {dd} 会替换成两位日期 */
/* {hh} 会替换成两位小时 */
/* {ii} 会替换成两位分钟 */
/* {ss} 会替换成两位秒 */
/* 非法字符 \ : * ? " < > | */
/* 具请体看线上文档: fex.baidu.com/ueditor/#use-format_upload_filename */
/* 涂鸦图片上传配置项 */
"scrawlActionName": "uploadscrawl", /* 执行上传涂鸦的action名称 */
"scrawlFieldName": "upfile", /* 提交的图片表单名称 */
"scrawlPathFormat": "data/attachment/image/{yyyy}{mm}{dd}/{time}{rand:6}", /* 上传保存路径,可以自定义保存路径和文件名格式 */
"scrawlMaxSize": 2048000, /* 上传大小限制,单位B */
"scrawlUrlPrefix": "http://test.oss-cn-hangzhou.aliyuncs.com", /* 图片访问路径前缀 */
"scrawlInsertAlign": "none",
/* 截图工具上传 */
"snapscreenActionName": "uploadimage", /* 执行上传截图的action名称 */
"snapscreenPathFormat": "/data/attachment/image/{yyyy}{mm}{dd}/{time}{rand:6}", /* 上传保存路径,可以自定义保存路径和文件名格式 */
"snapscreenUrlPrefix": "http://test.oss-cn-hangzhou.aliyuncs.com", /* 图片访问路径前缀 */
"snapscreenInsertAlign": "none", /* 插入的图片浮动方式 */
/* 抓取远程图片配置 */
"catcherLocalDomain": ["127.0.0.1", "localhost", "img.baidu.com"],
"catcherActionName": "catchimage", /* 执行抓取远程图片的action名称 */
"catcherFieldName": "source", /* 提交的图片列表表单名称 */
"catcherPathFormat": "/data/attachment/image/{yyyy}{mm}{dd}/{time}{rand:6}", /* 上传保存路径,可以自定义保存路径和文件名格式 */
"catcherUrlPrefix": "http://test.oss-cn-hangzhou.aliyuncs.com", /* 图片访问路径前缀 */
"catcherMaxSize": 2048000, /* 上传大小限制,单位B */
"catcherAllowFiles": [".png", ".jpg", ".jpeg", ".gif", ".bmp"], /* 抓取图片格式显示 */
/* 上传视频配置 */
"videoActionName": "uploadvideo", /* 执行上传视频的action名称 */
"videoFieldName": "upfile", /* 提交的视频表单名称 */
"videoPathFormat": "/data/attachment/video/{yyyy}{mm}{dd}/{time}{rand:6}", /* 上传保存路径,可以自定义保存路径和文件名格式 */
"videoUrlPrefix": "http://test.oss-cn-hangzhou.aliyuncs.com", /* 视频访问路径前缀 */
"videoMaxSize": 102400000, /* 上传大小限制,单位B,默认100MB */
"videoAllowFiles": [
".flv", ".swf", ".mkv", ".avi", ".rm", ".rmvb", ".mpeg", ".mpg",
".ogg", ".ogv", ".mov", ".wmv", ".mp4", ".webm", ".mp3", ".wav", ".mid"], /* 上传视频格式显示 */
/* 上传文件配置 */
"fileActionName": "uploadfile", /* controller里,执行上传视频的action名称 */
"fileFieldName": "upfile", /* 提交的文件表单名称 */
"filePathFormat": "/data/attachment/file/{yyyy}{mm}{dd}/{time}{rand:6}", /* 上传保存路径,可以自定义保存路径和文件名格式 */
"fileUrlPrefix": "http://test.oss-cn-hangzhou.aliyuncs.com", /* 文件访问路径前缀 */
"fileMaxSize": 51200000, /* 上传大小限制,单位B,默认50MB */
"fileAllowFiles": [
".png", ".jpg", ".jpeg", ".gif", ".bmp",
".flv", ".swf", ".mkv", ".avi", ".rm", ".rmvb", ".mpeg", ".mpg",
".ogg", ".ogv", ".mov", ".wmv", ".mp4", ".webm", ".mp3", ".wav", ".mid",
".rar", ".zip", ".tar", ".gz", ".7z", ".bz2", ".cab", ".iso",
".doc", ".docx", ".xls", ".xlsx", ".ppt", ".pptx", ".pdf", ".txt", ".md", ".xml"
], /* 上传文件格式显示 */
/* 列出指定目录下的图片 */
"imageManagerActionName": "listimage", /* 执行图片管理的action名称 */
"imageManagerListPath": "/data/attachment/image/", /* 指定要列出图片的目录 */
"imageManagerListSize": 20, /* 每次列出文件数量 */
"imageManagerUrlPrefix": "http://test.oss-cn-hangzhou.aliyuncs.com", /* 图片访问路径前缀 */
"imageManagerInsertAlign": "none", /* 插入的图片浮动方式 */
"imageManagerAllowFiles": [".png", ".jpg", ".jpeg", ".gif", ".bmp"], /* 列出的文件类型 */
/* 列出指定目录下的文件 */
"fileManagerActionName": "listfile", /* 执行文件管理的action名称 */
"fileManagerListPath": "/data/attachment/file/", /* 指定要列出文件的目录 */
"fileManagerUrlPrefix": "http://test.oss-cn-hangzhou.aliyuncs.com", /* 文件访问路径前缀 */
"fileManagerListSize": 20, /* 每次列出文件数量 */
"fileManagerAllowFiles": [
".png", ".jpg", ".jpeg", ".gif", ".bmp",
".flv", ".swf", ".mkv", ".avi", ".rm", ".rmvb", ".mpeg", ".mpg",
".ogg", ".ogv", ".mov", ".wmv", ".mp4", ".webm", ".mp3", ".wav", ".mid",
".rar", ".zip", ".tar", ".gz", ".7z", ".bz2", ".cab", ".iso",
".doc", ".docx", ".xls", ".xlsx", ".ppt", ".pptx", ".pdf", ".txt", ".md", ".xml"
] /* 列出的文件类型 */
}
1.3、action_upload.php、action_list.php、action_crawler.php这三个文件主要是引用上传到阿里云OSS的文件FileUpload.php,都加入如下代码即可
include (__DIR__."/../../../../../../source/core/widgets/upload/FileUpload.php");
FileUpload.php文件上传到阿里云OSS的代码
<?php
namespace source\core\widgets\upload;
use Yii;
use yii\base\Action;
use yii\base\ActionFilter;
use source\models\Upload;
use OSS\OssClient;
use OSS\Core\OssException;
use OSS\Http\RequestCore;
use OSS\Http\ResponseCore;
use source\core\widgets\encrypt\AesMask;
use source\models\User;
class FileUpload
{
const endpoint = "填写你的endpoint";
const accessKeyId = "填写你的accessKeyId";
const accessKeySecret = "填写你的accessKeyId";
//百度编辑器图片上传
public static function UploadUeditorPicture($file)
{
include (__DIR__."/../../../../vendor/aliyuncs/oss-sdk-php/src/OSS/OssClient.php");
include (__DIR__."/../../../../vendor/aliyuncs/oss-sdk-php/src/OSS/Core/OssException.php");
include (__DIR__."/../../../../vendor/aliyuncs/oss-sdk-php/src/OSS/Core/OssUtil.php");
include (__DIR__."/../../../../vendor/aliyuncs/oss-sdk-php/src/OSS/Core/MimeTypes.php");
include (__DIR__."/../../../../vendor/aliyuncs/oss-sdk-php/src/OSS/Http/RequestCore.php");
include (__DIR__."/../../../../vendor/aliyuncs/oss-sdk-php/src/OSS/Http/ResponseCore.php");
include (__DIR__."/../../../../vendor/aliyuncs/oss-sdk-php/src/OSS/Result/Result.php");
include (__DIR__."/../../../../vendor/aliyuncs/oss-sdk-php/src/OSS/Result/PutSetDeleteResult.php");
include ("/../encrypt/StrMask.php");
include ("/../encrypt/AesMask.php");
$ossClient = new \OSS\OssClient(self::accessKeyId, self::accessKeySecret, self::endpoint);
$data = ['id'=>1,'modules_name'=>'ueditor','user_id'=>1];
$model = array();
$bucket = 'test';
if(empty($data['id'])){
$model['status']="ID不能为空";
return $model;
}
if(!isset($data['modules_name'])){
$model['status']="模块名称不能为空";
return $model;
}
if(!isset($data['user_id'])){
$model['status']="用户id不能为空";
return $model;
}
$path = self::Encrypt($data['modules_name'],$data['id'],$data['user_id']);//对上传的路径加密
if(!empty($file)){
$randName = time() . rand(1000, 9999) . strtolower(strrchr($file['name'], '.'));
$name = $path.$randName;
$tempName=!empty($file['tmp_name'])?$file['tmp_name']:"";
$ossClient->uploadFile($bucket,$name,$tempName);
return ['path'=>$name,'randName'=>$randName];
}
return ['path'=>'','randName'=>''];
}
/**
* 删除附件
*
* @param path string y upload表返回的附件上传路径path 字段\n
* @return status string 结果信息
*/
static public function DownloadDelete($path)
{
$ossClient = new OssClient(self::accessKeyId, self::accessKeySecret, self::endpoint);
$bucket = "test";
if(!isset($path)){
$model['status']="附件路径不能为空";
return $model;
}
$ossClient->deleteObject($bucket, $path);
$model['status']="删除成功";
return $model;
}
/**
* 批量删除附件
*
* @param path string y upload表返回的附件上传路径path 字段\n
* @return status string 结果信息
*/
static public function DownloadDeletes($data)
{
$ossClient = new OssClient(self::accessKeyId, self::accessKeySecret, self::endpoint);
$bucket = "test";
if(!isset($data)){
$model['status']="删除数组不能为空";
return $model;
}
$ossClient->deleteObjects($bucket, $data);
$model['status']="删除成功";
return $model;
}
function getObject($object)
{
$ossClient = new OssClient(self::accessKeyId, self::accessKeySecret, self::endpoint);
$options = array();
$bucket = "test";
$timeout = 3600;
$options = NULL;
try {
$signedUrl = $ossClient->signUrl($bucket, $object, $timeout, "PUT");
} catch (OssException $e) {
printf(__FUNCTION__ . ": FAILED\n");
printf($e->getMessage() . "\n");
return;
}
print(__FUNCTION__ . ": signedUrl: " . $signedUrl . "\n");
$content = file_get_contents(__FILE__);
$request = new RequestCore($signedUrl);
$request->set_method('PUT');
$request->add_header('Content-Type', '');
$request->add_header('Content-Length', strlen($content));
$request->set_body($content);
$request->send_request();
$res = new ResponseCore($request->get_response_header(),
$request->get_response_body(), $request->get_response_code());
if ($res->isOK()) {
print(__FUNCTION__ . ": OK" . "\n");
} else {
print(__FUNCTION__ . ": FAILED" . "\n");
};
}
/**
* 加密路径
*
* @param array $data Y 参数数组(array('modules_name'=>$modules_name,'bucket'=>'test','path'=>'upload/accessory/14585506176746.jpg'))\n
* --modules_name string Y 模块名称\n
* --id string Y id\n
* @return status string 结果信息
*/
static public function Encrypt($modules_name,$id,$user_id='')
{
if(empty($user_id)){
$user_id = Yii::$app->user->id;
}
$modules_path = AesMask::encrypt($modules_name,'test');
$id_path = AesMask::encrypt($id,'test');
return "test/".$modules_path."/".$id_path."/";
}
}
?>
新增图片Controller的代码
public function actionCreate()
{
$username=!empty(Yii::$app->user->identity->attributes['username'])?Yii::$app->user->identity->attributes['username']:"";
$model = new Product();
$model->user_id=Yii::$app->user->id;
$model->user_name = $username;
$model->product_type=$this->product_type;
$model->loadDefaultValues();
$bodyModel = $this->getBodyModel();
$bodyModel->loadDefaultValues();
if(($r = $this->saveProduct($model, $bodyModel))!==false)
{
return $r;
}
//产品属性
$product_items=[];
return $this->render('create', [
'model' => $model,
'bodyModel' => $bodyModel,
'product_items'=>$product_items,
]);
}
public function saveProduct($model, $bodyModel)
{
$postDatas = Yii::$app->request->post();
if ($model->load($postDatas) && $bodyModel->load($postDatas) && $model->validate() && $bodyModel->validate()) {
if($model->summary===null|| $model->summary ==='')
{
if($bodyModel->hasAttribute('body'))
{
$product = strip_tags($bodyModel->body);
$pattern = '/\s/';//去除空白
$product = preg_replace($pattern, '', $product);
$model->summary=StringHelper::subStr($product,250);
}
}
if($model->save())
{
$bodyModel->product_id = $model->id;
$bodyModel->save();
//保存百度编辑器的图片
$this->saveUpload($bodyModel->body,$model->id);
//属性
if(!empty($postDatas['ProductItems'])){
ProductItems::deleteAll(['product_id'=>$model->id]);
foreach ($postDatas['ProductItems']['type'] as $key => $val) {
$modelItems = new ProductItems();
$modelItems->product_id = $model->id;
$modelItems->type = !empty($postDatas['ProductItems']['type'][$key])?$postDatas['ProductItems']['type'][$key]:"";
$modelItems->source = !empty($postDatas['ProductItems']['source'][$key])?$postDatas['ProductItems']['source'][$key]:"";
$modelItems->ticket_pat = !empty($postDatas['ProductItems']['ticket_pat'][$key])?$postDatas['ProductItems']['ticket_pat'][$key]:"";
$modelItems->ticket_pats = !empty($postDatas['ProductItems']['ticket_pats'][$key])?$postDatas['ProductItems']['ticket_pats'][$key]:"";
$modelItems->save();
}
}
return $this->redirect(['index']);
}
}
return false;
}
//保存图片
public function saveUpload($body,$task_id)
{
$error['status']="内容为空";
if(!empty($body) && $task_id){
$preg = '/<img.*?src=[\"|\']?(.*?)[\"|\']?\s.*?>/i'; //获取百度编辑器里提交的图片路径
preg_match_all($preg, $body, $imgArr);
if(!empty($imgArr[1])){
foreach ($imgArr[1] as $key => $val) {
$_imgArr = explode('/wpzx/', $val);
$path='wpzx/'.$_imgArr[1];
$suffix = pathinfo($_imgArr[1]);
$img_info = getimagesize($val);
$model= new Upload();
if($suffix['extension'] == 'jpg' || $suffix['extension'] == 'JPG'|| $suffix['extension'] == 'png'|| $suffix['extension'] == 'PNG'|| $suffix['extension'] == 'jpeg'){
$model->thumb = $path;
}
$model->task_id = $task_id;
$model->name = $suffix['basename'];
$model->path = $path;
$model->status = 1;
$model->user_id = Yii::$app->user->id;
$model->size = $img_info[0]*$img_info[1];
$model->type = $img_info['mime'];
$model->upload_time = time();
$model->module_id = 3;
$model->modules_name = 'product';
$model->target = 1;
if (!$model->save()) {
$error['status']="失败";
}
}
if($error['status']!="失败"){
return true;
}
return $error;
}
}
//删除upload与阿里云的图片
$upload=Upload::getUploadsAll($task_id,'product');
if(!empty($upload)){
FileUpload::DownloadDeletes(ArrayHelper::getColumn($upload, 'path'));
Upload::deleteAll(['task_id'=>$task_id,'modules_name'=>'product']);
}
}
//根据指定条件获取所有上传图片
public static function getUploadsAll($task_id,$modules_name)
{
$data=[];
$query=Upload::find()->where(['modules_name'=>$modules_name]);
if(!empty($task_id)){
$data=$query->andWhere(['task_id'=>$task_id])->all();
}else{
$data=$query->all();
}
return $data;
}
//upload表的字段如下,仅供参考
public function attributeLabels()
{
return [
'id' => 'ID',
'name' => '上传文件名',
'path' => '文件路径',
'status' => '上传状态',
'task_id' => '所属任务',
'user_id' => '所属用户',
'size' => '文件大小',
'type' => '文件类型',
'upload_time' => '上传时间',
'module_id' => '所属系统',
'thumb' => '缩略图',
];
}
新增图片Views的代码
<?php
use yii\helpers\Html;
use yii\bootstrap\ActiveForm;
use source\models\Product;
use source\models\Takonomy;
use source\libs\Common;
use source\core\widgets\ueditor\Ueditor;
/* @var $this yii\web\View */
/* @var $model app\models\Product */
/* @var $form yii\widgets\ActiveForm */
$filedOptions = [
'template' => "{label}{input}\n{error}",
'labelOptions' => [
'class' => 'control-label'
]
]
;
$takonomies = Takonomy::getArrayTree('product');
$options = Common::buildTreeOptions($takonomies, $model->takonomy_id);
?>
<div class="product-form ">
<?php
$form = ActiveForm::begin([
'options'=>[
'enctype'=>'multipart/form-data',
],
'fieldConfig' => [
'template' => "{label}<div class=\"col-md-8\">{input}</div>\n{error}",
'labelOptions' => [
'class' => 'col-md-4 control-label no-padding-left no-padding-right align-left'
]
],
]);
?>
<div class="row">
<div class="col-md-9">
<?= $form->field($model, 'title',$filedOptions)->textInput(['maxlength' => 256,'placeholder'=>'请输入标题'])?>
<?= $form->field($model, 'url_alias',$filedOptions)->textInput(['maxlength' => 128,'placeholder'=>'Url 地址'])?>
<hr class="hr">
<?=$form->field($bodyModel, 'body',$filedOptions)->widget(Ueditor::className(),[
'options'=>[
'focus'=>true,
'toolbars'=> [
['fullscreen', 'source', '|', 'undo', 'redo', '|', 'bold', 'italic', 'underline','removeformat','autotypeset', '|', 'forecolor', 'backcolor', 'selectall', 'cleardoc','|','fontfamily', 'fontsize', '|', 'justifyleft', 'justifycenter', '|', 'link', 'unlink','|', 'insertimage', 'emotion','attachment','|', 'preview', 'searchreplace']
],
],
'attributes'=>[
'style'=>'height:80px'
]
])?>
</div>
<div class="col-md-3 form-horizontal" >
<div class="form-group">
<?= Html::submitButton($model->isNewRecord ? '新建' : '编辑', ['class' => $model->isNewRecord ? 'btn btn-success' : 'btn btn-primary'])?>
</div>
</div>
</div>
<?php ActiveForm::end(); ?>
</div>
总结分析
1、要修改的地方还是挺多的,百度UEditor上传后获取图片路径保存到数据库处理起来也有点繁琐,如果你们有更好的方法,可以给我留言,咱们一块讨论。
2、以上我只是处理了图片上传到阿里云OSS,如果大家需要把视频,Mp3等等附件上传到阿里云OSS也是同样的方法,唯一的区别就是在提交表单的时候要获取到对应的视频,Mp3等等附件路径保存到数据库得处理一下。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。