| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200 |
- <?php
- namespace Longyi\ImageUpload\Services;
- use Illuminate\Http\UploadedFile;
- use Illuminate\Support\Facades\Storage;
- use Illuminate\Support\Str;
- use Intervention\Image\ImageManager;
- use Exception;
- use Aws\S3\S3Client;
- use Aws\Exception\AwsException;
- class ImageUploadService
- {
- /**
- * Upload an image to the configured storage disk.
- *
- * @param UploadedFile $file
- * @param string|null $directory Custom directory path
- * @return array
- * @throws Exception
- */
- public function upload(UploadedFile $file, ?string $directory = null): array
- {
- // Validate the file
- $this->validateFile($file);
- // Determine the disk to use
- $disk = config('image_upload.default_disk', 's3');
- // Generate directory path
- $uploadDirectory = $directory ?? config('image_upload.upload_directory', 'images/uploads');
- $path = $uploadDirectory . '/' . date('Ym/d');
- // Process and store the image
- if (Str::contains($file->getMimeType(), 'image')) {
- return $this->processAndStoreImage($file, $path, $disk);
- } else {
- return $this->storeFile($file, $path, $disk);
- }
- }
- /**
- * Upload multiple images.
- *
- * @param array $files
- * @param string|null $directory
- * @return array
- */
- public function uploadMultiple(array $files, ?string $directory = null): array
- {
- $results = [];
- foreach ($files as $file) {
- if ($file instanceof UploadedFile) {
- try {
- $results[] = $this->upload($file, $directory);
- } catch (Exception $e) {
- $results[] = [
- 'success' => false,
- 'error' => $e->getMessage(),
- 'original_name' => $file->getClientOriginalName(),
- ];
- }
- }
- }
- return $results;
- }
- /**
- * Validate the uploaded file.
- *
- * @param UploadedFile $file
- * @throws Exception
- */
- protected function validateFile(UploadedFile $file): void
- {
- // Check file size
- $maxSize = config('image_upload.max_size', 5120) * 1024; // Convert KB to bytes
- if ($file->getSize() > $maxSize) {
- throw new Exception(__('The file size exceeds the maximum allowed size of :size KB.', [
- 'size' => config('image_upload.max_size', 5120)
- ]));
- }
- // Check file type
- $allowedTypes = config('image_upload.allowed_types', []);
- if (!in_array($file->getMimeType(), $allowedTypes)) {
- throw new Exception(__('The file type is not allowed. Allowed types: :types', [
- 'types' => implode(', ', $allowedTypes)
- ]));
- }
- }
- /**
- * Process and store an image file.
- *
- * @param UploadedFile $file
- * @param string $path
- * @param string $disk
- * @return array
- */
- protected function processAndStoreImage(UploadedFile $file, string $path, string $disk): array
- {
- $manager = new ImageManager();
- $image = $manager->make($file)->encode('webp');
- $fileName = Str::random(40) . '.webp';
- $fullPath = $path . '/' . $fileName;
- // 方式一:使用原生 AWS SDK 绕过 Laravel Storage
- $s3Client = new S3Client([
- 'version' => 'latest',
- 'region' => env('AWS_DEFAULT_REGION'),
- 'credentials' => [
- 'key' => env('AWS_ACCESS_KEY_ID'),
- 'secret' => env('AWS_SECRET_ACCESS_KEY'),
- ],
- 'http' => [
- 'verify' => false, // 临时禁用 SSL 验证用于测试
- ],
- ]);
- $result = $s3Client->putObject([
- 'Bucket' => env('AWS_BUCKET'),
- 'Key' => $fullPath,
- 'Body' => (string) $image,
- 'ContentType' => 'image/webp',
- ]);
- return [
- 'success' => true,
- 'path' => $fullPath,
- 'url' => Storage::disk($disk)->url($fullPath),
- 'original_name' => $file->getClientOriginalName(),
- 'mime_type' => $file->getMimeType(),
- 'size' => $file->getSize(),
- 'disk' => $disk,
- ];
- }
- /**
- * Store a non-image file.
- *
- * @param UploadedFile $file
- * @param string $path
- * @param string $disk
- * @return array
- */
- protected function storeFile(UploadedFile $file, string $path, string $disk): array
- {
- try {
- $fileName = Str::random(40) . '.' . $file->getClientOriginalExtension();
- $fullPath = $path . '/' . $fileName;
- Storage::disk($disk)->putFileAs($path, $file, $fileName);
- return [
- 'success' => true,
- 'path' => $fullPath,
- 'url' => Storage::disk($disk)->url($fullPath),
- 'original_name' => $file->getClientOriginalName(),
- 'mime_type' => $file->getMimeType(),
- 'size' => $file->getSize(),
- 'disk' => $disk,
- ];
- } catch (Exception $e) {
- throw new Exception(__('Failed to store file: :error', ['error' => $e->getMessage()]));
- }
- }
- /**
- * Delete an image from storage.
- *
- * @param string $path
- * @param string|null $disk
- * @return bool
- */
- public function delete(string $path, ?string $disk = null): bool
- {
- $disk = $disk ?? config('image_upload.default_disk', 's3');
- return Storage::disk($disk)->delete($path);
- }
- /**
- * Get the URL for a stored image.
- *
- * @param string $path
- * @param string|null $disk
- * @return string
- */
- public function getUrl(string $path, ?string $disk = null): string
- {
- $disk = $disk ?? config('image_upload.default_disk', 's3');
- return Storage::disk($disk)->url($path);
- }
- }
|