# Longyi Image Upload Module
一个用于Bagisto的图片上传模块,支持上传到AWS S3或其他存储驱动。
## 功能特性
- ✅ 支持单张图片上传
- ✅ 支持多张图片批量上传
- ✅ 支持AWS S3存储
- ✅ 支持本地存储
- ✅ 自动图片优化(转换为WebP格式)
- ✅ 文件大小和类型验证
- ✅ 自定义上传目录
- ✅ 图片删除功能
- ✅ 中英文界面支持
- ✅ **管理后台和前端都支持**
- ✅ **提供Vue组件供前端使用**
## 安装
### 1. 添加依赖
在项目的根目录运行:
```bash
composer require longyi/image-upload
```
或者手动添加到 `composer.json`:
```json
{
"require": {
"longyi/image-upload": "^1.0"
}
}
```
### 2. 配置AWS S3(如果使用S3存储)
在 `.env` 文件中添加以下配置:
```env
# 设置默认上传磁盘为s3
IMAGE_UPLOAD_DISK=s3
# AWS S3 配置
AWS_ACCESS_KEY_ID=your-access-key-id
AWS_SECRET_ACCESS_KEY=your-secret-access-key
AWS_DEFAULT_REGION=your-region
AWS_BUCKET=your-bucket-name
AWS_URL=https://your-bucket.s3.your-region.amazonaws.com
AWS_USE_PATH_STYLE_ENDPOINT=false
# 可选:设置最大上传大小(KB)
IMAGE_UPLOAD_MAX_SIZE=5120
```
### 3. 发布配置文件(可选)
```bash
php artisan vendor:publish --provider="Longyi\ImageUpload\Providers\ImageUploadServiceProvider" --tag=config
```
### 4. 清除缓存
```bash
php artisan config:clear
php artisan cache:clear
```
## 使用方法
### 管理后台访问
访问管理后台的图片上传页面:
```
/admin/image-upload
```
### 前端 API 使用
前端用户可以通过 API 上传图片,所有接口都在 `/api/image-upload` 路径下。
#### 1. 上传单张图片(前端)
**请求:**
```http
POST /api/image-upload/upload
Content-Type: multipart/form-data
image: [file]
directory: shop/uploads (可选,默认为 shop/uploads)
```
**响应:**
```json
{
"success": true,
"message": "Image uploaded successfully",
"data": {
"success": true,
"path": "shop/uploads/2026/05/27/abc123.webp",
"url": "https://bucket.s3.region.amazonaws.com/shop/uploads/2026/05/27/abc123.webp",
"original_name": "photo.jpg",
"mime_type": "image/jpeg",
"size": 102400,
"disk": "s3"
}
}
```
#### 2. 上传多张图片(前端)
**请求:**
```http
POST /api/image-upload/upload-multiple
Content-Type: multipart/form-data
images[]: [file1]
images[]: [file2]
directory: shop/uploads (可选)
```
**限制:**
- 最多上传 10 张图片
- 每张不超过配置的最大大小
### Vue 组件使用
模块提供了一个现成的 Vue 组件,可以在前端页面中使用:
```vue
```
### JavaScript/Fetch 使用示例
如果你不使用 Vue,也可以直接用 JavaScript 调用 API:
```javascript
// 单张图片上传
async function uploadImage(file) {
const formData = new FormData();
formData.append('image', file);
formData.append('directory', 'custom/path');
try {
const response = await fetch('/api/image-upload/upload', {
method: 'POST',
body: formData,
headers: {
'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]')?.content
}
});
const data = await response.json();
if (data.success) {
console.log('上传成功:', data.data.url);
return data.data;
} else {
console.error('上传失败:', data.message);
}
} catch (error) {
console.error('错误:', error);
}
}
// 多张图片上传
async function uploadMultipleImages(files) {
const formData = new FormData();
files.forEach(file => {
formData.append('images[]', file);
});
formData.append('directory', 'custom/path');
try {
const response = await fetch('/api/image-upload/upload-multiple', {
method: 'POST',
body: formData,
headers: {
'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]')?.content
}
});
const data = await response.json();
if (data.success) {
console.log('上传成功:', data.data);
return data.data;
} else {
console.error('上传失败:', data.message);
}
} catch (error) {
console.error('错误:', error);
}
}
// 使用示例
document.getElementById('imageInput').addEventListener('change', async (e) => {
const file = e.target.files[0];
if (file) {
const result = await uploadImage(file);
// 使用 result.url 显示图片或保存到数据库
document.getElementById('preview').src = result.url;
}
});
```
### 管理后台 API 使用
以下 API 端点用于管理后台(需要管理员权限):
#### 1. 上传单张图片(管理后台)
**请求:**
```http
POST /admin/image-upload/upload
Content-Type: multipart/form-data
image: [file]
directory: custom/path (可选)
```
**响应:**
```json
{
"success": true,
"message": "Image uploaded successfully",
"data": {
"success": true,
"path": "images/uploads/2026/05/27/abc123.webp",
"url": "https://bucket.s3.region.amazonaws.com/images/uploads/2026/05/27/abc123.webp",
"original_name": "photo.jpg",
"mime_type": "image/jpeg",
"size": 102400,
"disk": "s3"
}
}
```
#### 2. 上传多张图片(管理后台)
**请求:**
```http
POST /admin/image-upload/upload-multiple
Content-Type: multipart/form-data
images[]: [file1]
images[]: [file2]
directory: custom/path (可选)
```
**响应:**
```json
{
"success": true,
"message": "2 images uploaded successfully, 0 failed",
"data": [
{
"success": true,
"path": "images/uploads/2026/05/27/abc123.webp",
"url": "https://...",
"original_name": "photo1.jpg",
"mime_type": "image/jpeg",
"size": 102400,
"disk": "s3"
},
{
"success": true,
"path": "images/uploads/2026/05/27/def456.webp",
"url": "https://...",
"original_name": "photo2.jpg",
"mime_type": "image/jpeg",
"size": 204800,
"disk": "s3"
}
]
}
```
#### 3. 删除图片(管理后台)
**请求:**
```http
DELETE /admin/image-upload/delete
Content-Type: application/json
{
"path": "images/uploads/2026/05/27/abc123.webp",
"disk": "s3" (可选)
}
```
**响应:**
```json
{
"success": true,
"message": "Image deleted successfully"
}
```
#### 4. 获取图片URL(管理后台)
**请求:**
```http
GET /admin/image-upload/url?path=images/uploads/2026/05/27/abc123.webp&disk=s3
```
**响应:**
```json
{
"success": true,
"url": "https://bucket.s3.region.amazonaws.com/images/uploads/2026/05/27/abc123.webp"
}
```
### API 路由对比
| 功能 | 管理后台路由 | 前端路由 | 说明 |
|------|------------|---------|------|
| 上传单张 | POST `/admin/image-upload/upload` | POST `/api/image-upload/upload` | 前端默认目录为 `shop/uploads` |
| 上传多张 | POST `/admin/image-upload/upload-multiple` | POST `/api/image-upload/upload-multiple` | 前端最多10张 |
| 删除图片 | DELETE `/admin/image-upload/delete` | DELETE `/api/image-upload/delete` | - |
| 获取URL | GET `/admin/image-upload/url` | GET `/api/image-upload/url` | - |
**主要区别:**
- **管理后台**:需要管理员权限,路径为 `/admin/*`
- **前端**:无需特殊权限(或需要登录),路径为 `/api/*`,默认上传到 `shop/uploads` 目录
## 代码中使用
```php
use Longyi\ImageUpload\Services\ImageUploadService;
// 注入服务
public function __construct(
protected ImageUploadService $imageUploadService
) {}
// 上传单张图片
public function uploadImage(Request $request)
{
$file = $request->file('image');
$result = $this->imageUploadService->upload($file, 'custom/directory');
if ($result['success']) {
// 使用 $result['url'] 或 $result['path']
}
}
// 上传多张图片
public function uploadImages(Request $request)
{
$files = $request->file('images');
$results = $this->imageUploadService->uploadMultiple($files, 'custom/directory');
foreach ($results as $result) {
if ($result['success']) {
// 处理成功的上传
}
}
}
// 删除图片
public function deleteImage(string $path)
{
$deleted = $this->imageUploadService->delete($path);
if ($deleted) {
// 删除成功
}
}
// 获取图片URL
public function getImageUrl(string $path)
{
$url = $this->imageUploadService->getUrl($path);
return $url;
}
```
## 配置说明
配置文件位于 `config/image_upload.php`:
```php
return [
// 默认存储磁盘:'local' 或 's3'
'default_disk' => env('IMAGE_UPLOAD_DISK', 's3'),
// 允许的图片类型
'allowed_types' => [
'image/jpeg',
'image/jpg',
'image/png',
'image/gif',
'image/webp',
'image/svg+xml',
],
// 最大文件大小(KB)
'max_size' => env('IMAGE_UPLOAD_MAX_SIZE', 5120),
// 上传目录
'upload_directory' => 'images/uploads',
// S3配置
's3' => [
'bucket' => env('AWS_BUCKET'),
'region' => env('AWS_DEFAULT_REGION'),
'visibility' => 'public',
],
];
```
## 扩展其他存储方式
要添加其他存储方式(如阿里云OSS、腾讯云COS等),只需:
1. 安装相应的Flysystem适配器
2. 在 `config/filesystems.php` 中配置新的disk
3. 修改 `IMAGE_UPLOAD_DISK` 环境变量或使用新的disk名称
例如,添加阿里云OSS:
```bash
composer require aliyuncs/oss-sdk-php
composer require jacobcyl/ali-oss-storage
```
在 `config/filesystems.php` 中添加:
```php
'oss' => [
'driver' => 'oss',
'access_id' => env('ALIYUN_ACCESS_KEY_ID'),
'access_key' => env('ALIYUN_ACCESS_KEY_SECRET'),
'bucket' => env('ALIYUN_BUCKET'),
'endpoint' => env('ALIYUN_ENDPOINT'),
],
```
然后设置 `IMAGE_UPLOAD_DISK=oss` 即可。
## 依赖要求
- PHP >= 8.1
- Laravel >= 10.0
- intervention/image
- league/flysystem-aws-s3-v3 (用于S3支持)
## 许可证
MIT License
## 作者
Longyi Team