diff --git a/.env.example b/.env.example index 903168a0..93d83861 100644 --- a/.env.example +++ b/.env.example @@ -4,7 +4,7 @@ APP_KEY= APP_DEBUG=true APP_URL=http://localhost -LOG_CHANNEL=stack +LOG_CHANNEL=daily LOG_DEPRECATIONS_CHANNEL=null LOG_LEVEL=debug diff --git a/app/Enums/ConfigKey.php b/app/Enums/ConfigKey.php new file mode 100644 index 00000000..44500915 --- /dev/null +++ b/app/Enums/ConfigKey.php @@ -0,0 +1,46 @@ +response($status, $message, $data); + } + + public function error(string $message = 'error', bool $status = false, array $data = []): array + { + return $this->response($status, $message, $data); + } + + public function response(bool $status, string $message = '', array $data = []): array + { + $data = $data ?: new \stdClass; + return compact('status', 'message', 'data'); + } +} diff --git a/app/Http/Controllers/Controller.php b/app/Http/Controllers/Controller.php index fc339615..1f4292d8 100644 --- a/app/Http/Controllers/Controller.php +++ b/app/Http/Controllers/Controller.php @@ -2,26 +2,29 @@ namespace App\Http\Controllers; +use App\Exceptions\UploadException; +use App\Http\Api; use App\Service\UploadService; use Illuminate\Foundation\Auth\Access\AuthorizesRequests; use Illuminate\Foundation\Bus\DispatchesJobs; use Illuminate\Foundation\Validation\ValidatesRequests; use Illuminate\Http\Request; use Illuminate\Routing\Controller as BaseController; +use Illuminate\Support\Facades\Log; class Controller extends BaseController { - use AuthorizesRequests, DispatchesJobs, ValidatesRequests; + use AuthorizesRequests, DispatchesJobs, ValidatesRequests, Api; public function upload(Request $request, UploadService $service): array { - // TODO 如果关闭了游客上传,返回404 - // TODO 检测IP是否超出上传限制 - // TODO 获取用户组 - // TODO 判断储存容量 - // TODO 获取策略列表,根据用户所选的策略上传 - // TODO 检测是否存在该图片,有则直接返回 - // TODO 图片保存至默认相册(若有) + try { + } catch (UploadException $e) { + return $this->error($e->getMessage()); + } catch (\Throwable $e) { + Log::error("Web 上传文件时发生异常,", ['message' => $e->getMessage(), 'trace' => $e->getTraceAsString()]); + return $this->error('上传失败,请稍后再试'); + } $data = [ 'url' => 'https://pic.iqy.ink/2021/12/12/e8cfd03eb787f.png', 'html' => '<img src="https://pic.iqy.ink/2021/12/12/e8cfd03eb787f.png" alt="e212bc43771ad6d391952732a1713e31.png" title="e212bc43771ad6d391952732a1713e31.png" />', diff --git a/app/Models/Group.php b/app/Models/Group.php index 2f349054..0b3ad921 100644 --- a/app/Models/Group.php +++ b/app/Models/Group.php @@ -2,6 +2,7 @@ namespace App\Models; +use App\Enums\GroupConfigKey; use Carbon\Carbon; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; @@ -37,14 +38,16 @@ class Group extends Model { static::creating(function (self $group) { $group->configs = collect([ - 'upload_max_size' => 5120, // 最大上传大小 - 'upload_single_num' => 3, // 单次同时上传数量 - 'is_need_review' => false, // 上传是否需要审查 - 'limit_per_day' => 0, // 每天可以上传数量,0 为不限制 - 'upload_allowed_types' => ['jpg', 'jpeg', 'gif', 'png', 'ico'], // 允许上传的文件类型 - 'path_naming_rule' => '{Y}/{m}/{d}', // 路径命名规则 - 'file_naming_rule' => '{uniqid}', // 文件命名规则 - 'user_initial_capacity' => 1048576, // 用户初始容量 + GroupConfigKey::MaximumFileSize => 5120, + GroupConfigKey::ConcurrentUploadNum => 3, + GroupConfigKey::IsUploadNeedsReview => false, + GroupConfigKey::LimitPerHour => 0, + GroupConfigKey::LimitPerDay => 0, + GroupConfigKey::LimitPerWeek => 0, + GroupConfigKey::LimitPerMonth => 0, + GroupConfigKey::AcceptedFileSuffixes => ['jpg', 'jpeg', 'gif', 'png', 'ico'], + GroupConfigKey::PathNamingRule => '{Y}/{m}/{d}', + GroupConfigKey::FileNamingRule => '{uniqid}', ])->merge($group->configs ?: []); }); } diff --git a/app/Models/User.php b/app/Models/User.php index 07ce7dca..2fbc3b65 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -2,6 +2,7 @@ namespace App\Models; +use App\Enums\UserConfigKey; use Carbon\Carbon; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Relations\BelongsTo; @@ -80,10 +81,9 @@ class User extends Authenticatable { static::creating(function (self $user) { $user->configs = collect([ - 'upload_default_album' => 0, // 默认上传相册 - 'upload_default_strategy' => 0, // 默认上传策略 - 'is_upload_show_preview', // 是否显示上传预览 - 'is_upload_auto_clear_preview', // 上传成功是否自动删除预览图 + UserConfigKey::DefaultAlbum => 0, + UserConfigKey::DefaultStrategy => 0, + UserConfigKey::IsAutoClearPreview, ])->merge($user->configs ?: []); }); } diff --git a/app/Service/UploadService.php b/app/Service/UploadService.php index 9d4f5552..f90acbd5 100644 --- a/app/Service/UploadService.php +++ b/app/Service/UploadService.php @@ -2,7 +2,20 @@ namespace App\Service; +use App\Models\Image; +use App\Models\User; +use Illuminate\Http\Request; + class UploadService { - + public function store(Request $request, ?User $user)//: Image + { + // TODO 如果关闭了游客上传,返回404 + // TODO 检测IP是否超出上传限制 + // TODO 获取用户组,无用户组则不受用户组配置限制 + // TODO 判断储存容量 + // TODO 获取策略列表,根据用户所选的策略上传 + // TODO 检测是否存在该图片,有则直接返回 + // TODO 图片保存至默认相册(若有) + } } diff --git a/app/Utils.php b/app/Utils.php new file mode 100644 index 00000000..2033aab9 --- /dev/null +++ b/app/Utils.php @@ -0,0 +1,11 @@ +=5.5" + }, + "require-dev": { + "phpunit/phpunit": "^4.8.35|^5.4.3" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "authors": [ + { + "name": "AWS SDK Common Runtime Team", + "email": "aws-sdk-common-runtime@amazon.com" + } + ], + "description": "AWS Common Runtime for PHP", + "homepage": "http://aws.amazon.com/sdkforphp", + "keywords": [ + "amazon", + "aws", + "crt", + "sdk" + ], + "support": { + "issues": "https://github.com/awslabs/aws-crt-php/issues", + "source": "https://github.com/awslabs/aws-crt-php/tree/v1.0.2" + }, + "time": "2021-09-03T22:57:30+00:00" + }, + { + "name": "aws/aws-sdk-php", + "version": "3.208.5", + "source": { + "type": "git", + "url": "https://github.com/aws/aws-sdk-php.git", + "reference": "58fa9d8b522b0afa260299179ff950c783ff0ee1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/58fa9d8b522b0afa260299179ff950c783ff0ee1", + "reference": "58fa9d8b522b0afa260299179ff950c783ff0ee1", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "aws/aws-crt-php": "^1.0.2", + "ext-json": "*", + "ext-pcre": "*", + "ext-simplexml": "*", + "guzzlehttp/guzzle": "^5.3.3|^6.2.1|^7.0", + "guzzlehttp/promises": "^1.4.0", + "guzzlehttp/psr7": "^1.7.0|^2.0", + "mtdowling/jmespath.php": "^2.6", + "php": ">=5.5" + }, + "require-dev": { + "andrewsville/php-token-reflection": "^1.4", + "aws/aws-php-sns-message-validator": "~1.0", + "behat/behat": "~3.0", + "doctrine/cache": "~1.4", + "ext-dom": "*", + "ext-openssl": "*", + "ext-pcntl": "*", + "ext-sockets": "*", + "nette/neon": "^2.3", + "paragonie/random_compat": ">= 2", + "phpunit/phpunit": "^4.8.35|^5.4.3", + "psr/cache": "^1.0", + "psr/simple-cache": "^1.0", + "sebastian/comparator": "^1.2.3" + }, + "suggest": { + "aws/aws-php-sns-message-validator": "To validate incoming SNS notifications", + "doctrine/cache": "To use the DoctrineCacheAdapter", + "ext-curl": "To send requests using cURL", + "ext-openssl": "Allows working with CloudFront private distributions and verifying received SNS messages", + "ext-sockets": "To use client-side monitoring" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0-dev" + } + }, + "autoload": { + "psr-4": { + "Aws\\": "src/" + }, + "files": [ + "src/functions.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "Apache-2.0" + ], + "authors": [ + { + "name": "Amazon Web Services", + "homepage": "http://aws.amazon.com" + } + ], + "description": "AWS SDK for PHP - Use Amazon Web Services in your PHP project", + "homepage": "http://aws.amazon.com/sdkforphp", + "keywords": [ + "amazon", + "aws", + "cloud", + "dynamodb", + "ec2", + "glacier", + "s3", + "sdk" + ], + "support": { + "forum": "https://forums.aws.amazon.com/forum.jspa?forumID=80", + "issues": "https://github.com/aws/aws-sdk-php/issues", + "source": "https://github.com/aws/aws-sdk-php/tree/3.208.5" + }, + "time": "2021-12-13T20:17:56+00:00" + }, { "name": "bensampo/laravel-enum", "version": "v4.1.0", @@ -2059,6 +2212,115 @@ ], "time": "2021-12-09T09:40:50+00:00" }, + { + "name": "league/flysystem-aws-s3-v3", + "version": "1.0.29", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/flysystem-aws-s3-v3.git", + "reference": "4e25cc0582a36a786c31115e419c6e40498f6972" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/flysystem-aws-s3-v3/zipball/4e25cc0582a36a786c31115e419c6e40498f6972", + "reference": "4e25cc0582a36a786c31115e419c6e40498f6972", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "aws/aws-sdk-php": "^3.20.0", + "league/flysystem": "^1.0.40", + "php": ">=5.5.0" + }, + "require-dev": { + "henrikbjorn/phpspec-code-coverage": "~1.0.1", + "phpspec/phpspec": "^2.0.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "psr-4": { + "League\\Flysystem\\AwsS3v3\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Frank de Jonge", + "email": "info@frenky.net" + } + ], + "description": "Flysystem adapter for the AWS S3 SDK v3.x", + "support": { + "issues": "https://github.com/thephpleague/flysystem-aws-s3-v3/issues", + "source": "https://github.com/thephpleague/flysystem-aws-s3-v3/tree/1.0.29" + }, + "time": "2020-10-08T18:58:37+00:00" + }, + { + "name": "league/flysystem-sftp", + "version": "1.0.22", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/flysystem-sftp.git", + "reference": "cab59dd2277e02fe46f5f23195672a02ed49774d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/flysystem-sftp/zipball/cab59dd2277e02fe46f5f23195672a02ed49774d", + "reference": "cab59dd2277e02fe46f5f23195672a02ed49774d", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "league/flysystem": "~1.0", + "php": ">=5.6.0", + "phpseclib/phpseclib": "~2.0" + }, + "require-dev": { + "mockery/mockery": "0.9.*", + "phpunit/phpunit": "^5.7.25" + }, + "type": "library", + "autoload": { + "psr-4": { + "League\\Flysystem\\Sftp\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Frank de Jonge", + "email": "info@frenky.net" + } + ], + "description": "Flysystem adapter for SFTP", + "support": { + "issues": "https://github.com/thephpleague/flysystem-sftp/issues", + "source": "https://github.com/thephpleague/flysystem-sftp/tree/master" + }, + "time": "2019-10-16T20:05:49+00:00" + }, { "name": "league/mime-type-detection", "version": "1.9.0", @@ -2226,6 +2488,73 @@ ], "time": "2021-10-01T21:08:31+00:00" }, + { + "name": "mtdowling/jmespath.php", + "version": "2.6.1", + "source": { + "type": "git", + "url": "https://github.com/jmespath/jmespath.php.git", + "reference": "9b87907a81b87bc76d19a7fb2d61e61486ee9edb" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/jmespath/jmespath.php/zipball/9b87907a81b87bc76d19a7fb2d61e61486ee9edb", + "reference": "9b87907a81b87bc76d19a7fb2d61e61486ee9edb", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": "^5.4 || ^7.0 || ^8.0", + "symfony/polyfill-mbstring": "^1.17" + }, + "require-dev": { + "composer/xdebug-handler": "^1.4 || ^2.0", + "phpunit/phpunit": "^4.8.36 || ^7.5.15" + }, + "bin": [ + "bin/jp.php" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.6-dev" + } + }, + "autoload": { + "psr-4": { + "JmesPath\\": "src/" + }, + "files": [ + "src/JmesPath.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + } + ], + "description": "Declaratively specify how to extract elements from a JSON document", + "keywords": [ + "json", + "jsonpath" + ], + "support": { + "issues": "https://github.com/jmespath/jmespath.php/issues", + "source": "https://github.com/jmespath/jmespath.php/tree/2.6.1" + }, + "time": "2021-06-14T00:11:39+00:00" + }, { "name": "nesbot/carbon", "version": "2.55.2", @@ -2620,6 +2949,59 @@ }, "time": "2021-04-09T13:42:10+00:00" }, + { + "name": "overtrue/flysystem-qiniu", + "version": "1.0.5", + "source": { + "type": "git", + "url": "https://github.com/overtrue/flysystem-qiniu.git", + "reference": "642731719ecba8826e095e2395e379c2a4910c80" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/overtrue/flysystem-qiniu/zipball/642731719ecba8826e095e2395e379c2a4910c80", + "reference": "642731719ecba8826e095e2395e379c2a4910c80", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "league/flysystem": "^1.0", + "php": ">=5.5.9", + "qiniu/php-sdk": "^7.2" + }, + "require-dev": { + "mockery/mockery": "1.3.1", + "php": ">=5.6.0", + "phpunit/phpunit": "~8.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Overtrue\\Flysystem\\Qiniu\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "overtrue", + "email": "i@overtrue.me" + } + ], + "description": "Flysystem adapter for the Qiniu storage.", + "support": { + "issues": "https://github.com/overtrue/flysystem-qiniu/issues", + "source": "https://github.com/overtrue/flysystem-qiniu/tree/master" + }, + "time": "2020-02-21T10:46:56+00:00" + }, { "name": "overtrue/laravel-lang", "version": "5.0.2", @@ -2768,6 +3150,121 @@ ], "time": "2021-12-04T23:24:31+00:00" }, + { + "name": "phpseclib/phpseclib", + "version": "2.0.35", + "source": { + "type": "git", + "url": "https://github.com/phpseclib/phpseclib.git", + "reference": "4e16cf3f5f927a7d3f5317820af795c0366c0420" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/4e16cf3f5f927a7d3f5317820af795c0366c0420", + "reference": "4e16cf3f5f927a7d3f5317820af795c0366c0420", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "phing/phing": "~2.7", + "phpunit/phpunit": "^4.8.35|^5.7|^6.0|^9.4", + "squizlabs/php_codesniffer": "~2.0" + }, + "suggest": { + "ext-gmp": "Install the GMP (GNU Multiple Precision) extension in order to speed up arbitrary precision integer arithmetic operations.", + "ext-libsodium": "SSH2/SFTP can make use of some algorithms provided by the libsodium-php extension.", + "ext-mcrypt": "Install the Mcrypt extension in order to speed up a few other cryptographic operations.", + "ext-openssl": "Install the OpenSSL extension in order to speed up a wide variety of cryptographic operations." + }, + "type": "library", + "autoload": { + "files": [ + "phpseclib/bootstrap.php" + ], + "psr-4": { + "phpseclib\\": "phpseclib/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jim Wigginton", + "email": "terrafrost@php.net", + "role": "Lead Developer" + }, + { + "name": "Patrick Monnerat", + "email": "pm@datasphere.ch", + "role": "Developer" + }, + { + "name": "Andreas Fischer", + "email": "bantu@phpbb.com", + "role": "Developer" + }, + { + "name": "Hans-Jürgen Petrich", + "email": "petrich@tronic-media.com", + "role": "Developer" + }, + { + "name": "Graham Campbell", + "email": "graham@alt-three.com", + "role": "Developer" + } + ], + "description": "PHP Secure Communications Library - Pure-PHP implementations of RSA, AES, SSH2, SFTP, X.509 etc.", + "homepage": "http://phpseclib.sourceforge.net", + "keywords": [ + "BigInteger", + "aes", + "asn.1", + "asn1", + "blowfish", + "crypto", + "cryptography", + "encryption", + "rsa", + "security", + "sftp", + "signature", + "signing", + "ssh", + "twofish", + "x.509", + "x509" + ], + "support": { + "issues": "https://github.com/phpseclib/phpseclib/issues", + "source": "https://github.com/phpseclib/phpseclib/tree/2.0.35" + }, + "funding": [ + { + "url": "https://github.com/terrafrost", + "type": "github" + }, + { + "url": "https://www.patreon.com/phpseclib", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/phpseclib/phpseclib", + "type": "tidelift" + } + ], + "time": "2021-11-28T23:30:39+00:00" + }, { "name": "psr/container", "version": "1.1.2", @@ -3250,6 +3747,68 @@ }, "time": "2021-11-30T14:05:36+00:00" }, + { + "name": "qiniu/php-sdk", + "version": "v7.4.1", + "source": { + "type": "git", + "url": "https://github.com/qiniu/php-sdk.git", + "reference": "10c7ead8357743b4b987a335c14964fb07700d57" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/qiniu/php-sdk/zipball/10c7ead8357743b4b987a335c14964fb07700d57", + "reference": "10c7ead8357743b4b987a335c14964fb07700d57", + "shasum": "", + "mirrors": [ + { + "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", + "preferred": true + } + ] + }, + "require": { + "php": ">=5.3.3" + }, + "require-dev": { + "paragonie/random_compat": ">=2", + "phpunit/phpunit": "~4.0", + "squizlabs/php_codesniffer": "~3.6" + }, + "type": "library", + "autoload": { + "psr-4": { + "Qiniu\\": "src/Qiniu" + }, + "files": [ + "src/Qiniu/functions.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Qiniu", + "email": "sdk@qiniu.com", + "homepage": "http://www.qiniu.com" + } + ], + "description": "Qiniu Resource (Cloud) Storage SDK for PHP", + "homepage": "http://developer.qiniu.com/", + "keywords": [ + "cloud", + "qiniu", + "sdk", + "storage" + ], + "support": { + "issues": "https://github.com/qiniu/php-sdk/issues", + "source": "https://github.com/qiniu/php-sdk/tree/v7.4.1" + }, + "time": "2021-09-24T09:39:16+00:00" + }, { "name": "ralouphie/getallheaders", "version": "3.0.3", diff --git a/resources/views/components/upload.blade.php b/resources/views/components/upload.blade.php index 4bf11a73..5d9f71ef 100644 --- a/resources/views/components/upload.blade.php +++ b/resources/views/components/upload.blade.php @@ -197,7 +197,7 @@ } $links.show(); } else { - setStatus(data, UPLOAD_ERROR, response.message); + setStatus(data, UPLOAD_ERROR, "上传失败, " + response.message); // 重新显示上传按钮 data.$preview.find('[data-operate="upload"]').show(); }