这个项目是本地执行的一个脚本,业务人员会把做好的大图素材放到google drive上,然后项目所在的机器会装一个Google drive的app,目的是把google drive上的文件素材同步到本地文件夹中(怎么同步请自行搜索)
我用的是laravel框架,写在了conslole命令行里,定时执行这个脚本,大家也可以放到线上,对接google drive的webhook(我没试),然后根据通知自动触发任务
项目需要安装第三方图片处理包,我用的是Intervention\Image这个包,composer安装下
上代码
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
use Intervention\Image\ImageManagerStatic as Image;
class CutImage extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'cut-image';
/**
* The console command description.
*
* @var string
*/
protected $description = '自动裁剪google drive里的最新修改的图片并上传到Google storage';
const FILE_PATH = "/home/vagrant/cao";
const FILE_PATH_TEMP = "/home/vagrant/cao-temp";
const MID_H = 1024;
const MID_NAME = 'mid-';
const SM_H = 512;
const SM_NAME = 'small-';
const ICON_H = 128;
const ICON_NAME = 'icon-';
const STORAGE_FOLDER = 'wox-materials';
const STORAGE_BUCKET = 'gs://storage-custom.dollarhoo-test.me/';
public function handle()
{
$fileTemp = escapeshellarg(self::FILE_PATH_TEMP); // 对命令行参数进行安全转义
$originFile = self::FILE_PATH;
try {
//按修改时间过滤文件并且复制到临时文件夹
$this->filterMoveImageToTemp($originFile);
//获取临时文件夹里的图片进行裁剪上传才做
$file = self::FILE_PATH_TEMP;
$imagePathLists = $this->formatImagePathMap($this->getImageList($file));
} catch (\Exception $e) {
echo "++++++++++++++++++++++【发生错误】+++++++++++++++++++++\n";
echo "错误信息:" . $e->getMessage() . "\n";
echo "错误文件:" . $e->getFile() . "\n";
echo "错误行:" . $e->getLine() . "\n";
echo "+++++++++++++++++++++++++++++++++++++++++++++++++++++\n";
$imagePathLists = [];
//删除临时文件夹
$shell = `rm -rf $fileTemp`;
echo $shell;
//todo:钉钉报警
}
$picNum = 1;
$all = count($imagePathLists);
echo "总共【{$all}】张图片\n";
sleep(1);
echo "开始处理第一张图\n";
foreach ($imagePathLists as $imagePath) {
try {
$imageName = array_reverse(explode("/", $imagePath))[0];
//先上传原图
$this->moveImageToStorage($imagePath);
echo "*******************【正在处理$imagePath 】*******************\n";
//开始裁剪
$img = Image::make($imagePath);
$originW = $img->getWidth();
$originH = $img->getHeight();
//等比例计算
$midW = self::MID_H / $originH * $originW;
$smW = self::SM_H / $originH * $originW;
$iconW = self::ICON_H / $originH * $originW;
//mid image
$img->resize($midW, self::MID_H);
$mageResizeName = self::MID_NAME . $imageName;
$midImagePath = str_replace($imageName, $mageResizeName, $imagePath);
$img->save($midImagePath);
//google storage sdk ,同步处理好的图片到google storage
$this->moveImageToStorage($midImagePath);
echo "*******************【正在处理$midImagePath 】*******************\n";
//small image
$img->resize($smW, self::SM_H);
$mageResizeName = self::SM_NAME . $imageName;
$smallImagePath = str_replace($imageName, $mageResizeName, $imagePath);
$img->save($smallImagePath);
//google storage sdk ,同步处理好的图片到google storage
$this->moveImageToStorage($smallImagePath);
echo "*******************【正在处理 $smallImagePath 】*******************\n";
//icon image
$img->resize($iconW, self::ICON_H);
$mageResizeName = self::ICON_NAME . $imageName;
$iconImagePath = str_replace($imageName, $mageResizeName, $imagePath);
$img->save($iconImagePath);
//google storage sdk ,同步处理好的图片到google storage
$this->moveImageToStorage($iconImagePath);
echo "*******************【正在处理 $iconImagePath 】*******************\n";
echo "===================================================================\n";
$picNum++;
if ($picNum <= $all) {
echo "开始处理第{$picNum}张图\n";
}
} catch (\Exception $e) {
echo "++++++++++++++++++++++【发生错误】+++++++++++++++++++++\n";
echo "错误信息:" . $e->getMessage() . "\n";
echo "错误文件:" . $e->getFile() . "\n";
echo "错误行:" . $e->getLine() . "\n";
echo "+++++++++++++++++++++++++++++++++++++++++++++++++++++\n";
continue;
//todo:钉钉报警
}
}
//删除临时文件夹
$shell = `rm -rf $fileTemp`;
echo $shell;
echo "+++++++++++++++【所有图处理完毕!】++++++++++++++++++++\n";
}
/**
* 上传临时文件夹里的文件到Google storage
* @param string $tempImagePath 临时文件夹里的图片位置
*/
public function moveImageToStorage(string $tempImagePath)
{
$storagePath = escapeshellarg(self::STORAGE_BUCKET . self::STORAGE_FOLDER . str_replace(self::FILE_PATH_TEMP, '', $tempImagePath));
$tempImagePath = escapeshellarg($tempImagePath);
$shell = `/home/vagrant/google-cloud-sdk/bin/gsutil cp -r $tempImagePath $storagePath`;
echo $shell;
}
/**遍历临时文件夹获取所有图片树状图
* @param string $pathName
* @return array
*/
public function getImageList(string $pathName): array
{
//将结果保存在result变量中
$result = array();
$temp = array();
//判断传入的变量是否是目录
if (!is_dir($pathName) || !is_readable($pathName)) {
return [];
}
//取出目录中的文件和子目录名,使用scandir函数
$allFiles = scandir($pathName);
//遍历他们
foreach ($allFiles as $fileName) {
//判断是否是.和..因为这两个东西神马也不是。。。
if (in_array($fileName, array('.', '..'))) {
continue;
}
//路径加文件名
$fullName = $pathName . '/' . $fileName;
//如果是目录的话就继续遍历这个目录
if (is_dir($fullName)) {
//将这个目录中的文件信息存入到数组中
$result[$fullName . '/'] = $this->getImageList($fullName);
} else {
//如果是文件就先存入临时变量
$temp[] = $fileName;
}
}
//取出文件
if ($temp) {
foreach ($temp as $f) {
$result[] = $f;
}
}
return $result;
}
/**
* 遍历原始文件夹,并且按照修改时间过滤文件,并且复制到临时文件夹
* @param string $originFile
*/
public function filterMoveImageToTemp(string $originFile)
{
//判断传入的变量是否是目录
if (!(!is_dir($originFile) || !is_readable($originFile))) {
//取出目录中的文件和子目录名,使用scandir函数
$allFiles = scandir($originFile);
//遍历他们
foreach ($allFiles as $fileName) {
//判断是否是.和..因为这两个东西神马也不是。。。
if (in_array($fileName, array('.', '..'))) {
continue;
}
//路径加文件名
$fullName = $originFile . '/' . $fileName;
//如果是目录的话就继续遍历这个目录
if (is_dir($fullName)) {
//将这个目录中的文件信息存入到数组中
$this->filterMoveImageToTemp($fullName);
} else {
$tempPathName = str_replace(self::FILE_PATH, self::FILE_PATH_TEMP, $originFile);
//创建临时文件夹
$this->mkdirs($tempPathName);
$shell = `find $originFile -mtime -5 -type f | xargs -i cp {} $tempPathName`;
echo $shell;
}
}
}
}
/**扁平化数组
* @param $arr
* @return array
*/
public function flatten($arr): array
{
$result = [];
global $a;
foreach ($arr as $k => $v) {
if (is_array($v)) {
$a = $k;
$result = array_merge($result, $this->flatten($v));
} else if (is_numeric($k)) {
$result[$a][] = $v;
} else {
$result[$k] = $v;
}
}
return $result;
}
/**
* 整理获取到的树状文件夹图片列表成一维数组
* @param array $imagePathLists
* @return array
*/
public function formatImagePathMap(array $imagePathLists): array
{
$imagePathLists = $this->flatten($imagePathLists);
$imageList = [];
foreach ($imagePathLists as $path => $imageNameLists) {
foreach ($imageNameLists as $imageName)
$imageList[] = $path . $imageName;
}
return $imageList;
}
/**
* 判断文件夹是否存在,不存在就创建
* @param $dir
* @param int $mode
* @return bool
*/
public function mkdirs($dir, int $mode = 0777): bool
{
if (is_dir($dir) || @mkdir($dir, $mode))
return TRUE;
if (!$this->mkdirs(dirname($dir), $mode))
return FALSE;
return @mkdir($dir, $mode);
}
}