Files
laravel_swoole/app/Services/System/UploadService.php

160 lines
4.8 KiB
PHP

<?php
namespace App\Services\System;
use Illuminate\Http\UploadedFile;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str;
use Intervention\Image\ImageManager;
use Intervention\Image\Drivers\Gd\Driver;
class UploadService
{
protected $disk;
protected $allowedImageTypes = ['jpg', 'jpeg', 'png', 'gif', 'webp', 'bmp'];
protected $allowedFileTypes = ['pdf', 'doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx', 'zip', 'rar', 'txt'];
protected $maxFileSize = 10 * 1024 * 1024; // 10MB
public function __construct()
{
$this->disk = Storage::disk('public');
$this->imageManager = new ImageManager(new Driver());
}
public function upload(UploadedFile $file, string $directory = 'uploads', array $options = []): array
{
$extension = strtolower($file->getClientOriginalExtension());
if (!$this->validateFile($file, $extension)) {
throw new \Exception('文件验证失败');
}
$fileName = $this->generateFileName($file, $extension);
$filePath = $directory . '/' . date('Ymd') . '/' . $fileName;
if (in_array($extension, $this->allowedImageTypes) && isset($options['compress'])) {
$this->compressImage($file, $filePath, $options);
} else {
$this->disk->put($filePath, file_get_contents($file));
}
$url = $this->disk->url($filePath);
$fullPath = $this->disk->path($filePath);
return [
'url' => $url,
'path' => $filePath,
'name' => $file->getClientOriginalName(),
'size' => $file->getSize(),
'mime_type' => $file->getMimeType(),
'extension' => $extension,
];
}
public function uploadMultiple(array $files, string $directory = 'uploads', array $options = []): array
{
$results = [];
foreach ($files as $file) {
if ($file instanceof UploadedFile) {
$results[] = $this->upload($file, $directory, $options);
}
}
return $results;
}
public function uploadBase64(string $base64, string $directory = 'uploads', string $fileName = null): array
{
if (preg_match('/^data:image\/(\w+);base64,/', $base64, $matches)) {
$type = $matches[1];
$extension = $type;
$data = substr($base64, strpos($base64, ',') + 1);
$data = base64_decode($data);
if (!$data) {
throw new \Exception('Base64解码失败');
}
$fileName = $fileName ?: $this->generateUniqueFileName($extension);
$filePath = $directory . '/' . date('Ymd') . '/' . $fileName;
$this->disk->put($filePath, $data);
return [
'url' => $this->disk->url($filePath),
'path' => $filePath,
'name' => $fileName,
'size' => strlen($data),
'mime_type' => 'image/' . $type,
'extension' => $extension,
];
}
throw new \Exception('无效的Base64图片数据');
}
public function delete(string $path): bool
{
if ($this->disk->exists($path)) {
return $this->disk->delete($path);
}
return false;
}
public function deleteMultiple(array $paths): bool
{
foreach ($paths as $path) {
$this->delete($path);
}
return true;
}
private function validateFile(UploadedFile $file, string $extension): bool
{
if ($file->getSize() > $this->maxFileSize) {
throw new \Exception('文件大小超过限制');
}
$allowedTypes = array_merge($this->allowedImageTypes, $this->allowedFileTypes);
if (!in_array($extension, $allowedTypes)) {
throw new \Exception('不允许的文件类型');
}
return true;
}
private function generateFileName(UploadedFile $file, string $extension): string
{
return uniqid() . '_' . Str::random(6) . '.' . $extension;
}
private function generateUniqueFileName(string $extension): string
{
return uniqid() . '_' . Str::random(6) . '.' . $extension;
}
private function compressImage(UploadedFile $file, string $filePath, array $options): void
{
$quality = $options['quality'] ?? 80;
$width = $options['width'] ?? null;
$height = $options['height'] ?? null;
$image = $this->imageManager->read($file);
if ($width || $height) {
$image->scale($width, $height);
}
$encoded = $image->toJpeg(quality: $quality);
$this->disk->put($filePath, (string) $encoded);
}
public function getFileUrl(string $path): string
{
return $this->disk->url($path);
}
public function fileExists(string $path): bool
{
return $this->disk->exists($path);
}
}