招标
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

278 lines
8.2 KiB

<?php
namespace app;
use app\admin\model\system\Resource;
use OSS\Core\OssException;
use sdModule\common\Sc;
use sdModule\image\Image;
use think\facade\App;
use think\file\UploadedFile;
use app\common\SdException;
use app\common\ResponseJson;
class SystemUpload
{
const UPLOAD_DIR = 'upload_resource';
private string $verify_type = 'image';
private const VERIFY_RULE = [
'image' => [
'mime' => ['image/jpeg', 'image/jpg' , 'image/png', 'image/gif', 'image/bmp', 'image/vnd.microsoft.icon', 'image/webp'],
'ext' => ['jpg', 'jpeg', 'png', 'bmp', 'ico', 'webp', 'gif']
],
'excel' => [
'mime' => ['application/vnd.ms-excel', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', 'application/zip', 'text/csv'],
'ext' => ['xls', 'xlsx', '.csv'],
],
'video' => [
'mime' => ['video/x-msvideo', 'video/mpeg', 'video/ogg', 'video/webm', 'video/mp4'],
'ext' => ['webm', 'avi', 'mpeg', 'ogv', 'mp4'],
],
'audio' => [
'mime' => ['audio/mpeg', 'audio/ogg', 'audio/wav', 'audio/webm'],
'ext' => ['weba', 'wav', 'mp3', 'oga'],
],
'word' => [
'mime' => ['application/msword', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document','application/x-empty'],
'ext' => ['doc', 'docx'],
],
'pdf' => [
'mime'=>['application/pdf'],
'ext' => ['pdf']
]
];
/**
* 文件验证
* @param string $type
* @return UploadedFile
* @throws SdException
*/
/**
* 文件验证
* @param string $type
* @return UploadedFile
* @throws SdException
*/
private function fileVerify($type = null)
{
if (!$files = request()->file()) {
throw new SdException('无上传文件');
}
if (!class_exists('finfo')) {
throw new SdException('请安装fileinfo扩展');
}
$file_form_name = version_compare(PHP_VERSION,'7.3.0', '<') ?
array_keys($files)[0] : array_key_first($files);
$this->verify_type = $type === null ? (string)$file_form_name : $type;
/** @var UploadedFile $file */
$file = $files[$file_form_name];
$this->fileTypeVerify();
$this->mimeVerify($file);
return $file;
}
/**
* 文件类型验证
* @throws SdException
*/
public function fileTypeVerify()
{
$allow = $this->verify_type === 'all';
foreach (explode('*', $this->verify_type) as $verify_type) {
if (isset(self::VERIFY_RULE[$verify_type])) {
$allow = true;
break;
}
}
if (!$allow) {
throw new SdException('文件错误');
}
}
/**
* mime 验证
* @param UploadedFile $file
* @throws SdException
*/
private function mimeVerify($file)
{
$allow = $this->verify_type === 'all';
foreach (explode('*', $this->verify_type) as $verify_type) {
$rule = self::VERIFY_RULE[$verify_type];
if (in_array($file->getMime(), $rule['mime']) && in_array($file->getOriginalExtension(), $rule['ext'])) {
$allow = true;
break;
}
}
if (!$allow) {
throw new SdException('上传文件错误');
}
}
/**
* 图片上传
* @return \think\response\Json
* @throws SdException
* @throws \Throwable
*/
public function imageUpload()
{
return $this->localhostUpload($this->fileVerify('image'));
}
/**
* 文件上传
* @return \think\response\Json
* @throws SdException
* @throws \Throwable
*/
public function fileUpload()
{
return $this->localhostUpload($this->fileVerify());
}
/**
* 本地文件存储
* @param UploadedFile $file
* @return \think\response\Json
* @throws SdException
* @throws \Throwable
*/
private function localhostUpload($file)
{
try {
// 判断是否已经存在
$hasFile = Resource::getDataByWhere(['md5' => $file->md5()],true);
if (!$hasFile->isEmpty() && $this->fileCheck($hasFile->path)) {
$this->thumbnail($hasFile->path);
$data = $this->verify_type === 'image' ? strtr($hasFile->path, ['\\' => '/'])
: data_only($hasFile->toArray(), ['id', 'tag']);
return ResponseJson::success($data);
}
// 上传到本地服务器
$save_name = \think\facade\Filesystem::disk(in_array($this->verify_type, ['image']) ? 'public' : 'file')
->putFile( env('UPLOAD_DIR', self::UPLOAD_DIR), $file);
$this->thumbnail($save_name);
$data = [
'tag' => substr($file->getOriginalName(), 0, 255),
'path' => strtr($save_name, ['\\' => '/']),
'md5' => $file->md5(),
];
if ($hasFile->isEmpty()) {
$id = Resource::insertGetId(array_merge($data, ['create_time' => datetime(), 'update_time' => datetime()]));
}else{
Resource::update($data, ['md5' => $file->md5()]);
$id = $hasFile->id;
}
$data = $this->verify_type === 'image' ? strtr($save_name, ['\\' => '/'])
: ['id' => $id, 'tag' => $data['tag']];
return ResponseJson::success($data);
} catch (\Throwable $e) {
if (env('APP_DEBUG')) {
throw $e;
}
throw new SdException($e->getMessage());
}
}
/**
* 文件检测
* @param string $path
* @return bool
*/
private function fileCheck(string $path)
{
$root = in_array($this->verify_type, ['image', 'video'])
? config('filesystem.disk.public.root')
: config('filesystem.disk.file.root');
return file_exists($root . strtr($path, ['\\' => '/']));
}
/**
* 生成缩略图
* @param string $save_name 图片相对根目录路径
*/
private function thumbnail(string $save_name)
{
$file = App::getRootPath() . '/public/' . $save_name;
if(env('THUMBNAIL') && $this->verify_type === 'image' && file_exists($file)){
Image::thumbnail($file, 0.5)->compressImg(explode('.', $save_name)[0] . "_thumbnail");
}
}
/**
* 阿里云文件上传
* @return \think\response\Json
* @throws \Exception
*/
public function AlyUpload()
{
try {
if (empty($_FILES['file'])) {
return ResponseJson::fail('无上传文件');
}
$result = Sc::aLiYunOSS()->uploadFile('file');
} catch (OssException $e) {
throw new SdException($e->getErrorMessage());
}
return ResponseJson::success($result);
}
/**
* @return \think\response\Json
* @throws SdException
*/
public function base64ImageUpload()
{
$resource = request()->post('resource');
$md5 = md5($resource);
if (!preg_match('/^(data:\s*image\/(\w+);base64,)/', $resource, $result)) {
throw new SdException('资源格式错误!');
}
$path = implode(DIRECTORY_SEPARATOR, [env('UPLOAD_DIR', self::UPLOAD_DIR), date('Ym'), date('d'), $md5 . '.' . $result[2]]);
$hasFile = Resource::addSoftDelWhere(['md5' => $md5])->value('path');
if ($hasFile) {
return ResponseJson::success(strtr($hasFile, ['\\' => '/']));
}
if (!is_dir(dirname(config('filesystem.disks.public.root') . $path))) {
mkdir(dirname(config('filesystem.disks.public.root') . $path), 0777, true);
}
if (!file_put_contents(config('filesystem.disks.public.root'). $path,
base64_decode(str_replace($result[1], '', $resource)))){
throw new SdException('失败!');
}
$path = strtr($path, ['\\' => '/']);
// 记录此文件
Resource::create([
'tag' => '',
'path' => $path,
'md5' => $md5,
]);
return ResponseJson::success($path);
}
}