160 lines
4.8 KiB
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);
|
|
}
|
|
}
|