laobai/cloud-storage
最新稳定版本:v1.6.0
Composer 安装命令:
composer require laobai/cloud-storage
包简介
云存储上传组件,支持七牛云/本地存储,自动生成视频封面、图片缩略图、文字水印,兼容ThinkPHP5/6/8
README 文档
README
适用于 ThinkPHP5/6/8 的云存储上传组件,支持七牛云/本地存储,自动生成视频封面、图片缩略图、文字水印,兼容 PHP7.0 - PHP8.*
设计理念
极简调用,智能处理 - 只需传入上传字段名,其他一切(文件验证、自动识别类型、生成缩略图/封面/水印、返回统一格式)全部由组件自动完成。
安装
composer require laobai/cloud-storage
配置 (.env)
CLOUD_STORAGE_DRIVER=qiniu
# 七牛云配置
QINIU_ACCESS_KEY=your_access_key
QINIU_SECRET_KEY=your_secret_key
QINIU_BUCKET=your_bucket
QINIU_DOMAIN=https://cdn.example.com
QINIU_ZONE=z0
# FFmpeg 路径(生成视频封面必需)
FFMPEG_PATH=/usr/bin/ffmpeg
# 水印配置
WATERMARK_TEXT=© YourSite.com
FFmpeg 安装
视频封面功能依赖 FFmpeg,必须安装:
# Debian/Ubuntu
apt install ffmpeg
# CentOS/RHEL
yum install epel-release && yum install ffmpeg
# macOS
brew install ffmpeg
注意:
- 如果未安装 FFmpeg,上传视频时不传
video_cover_size选项可以正常上传 - 如果传了
video_cover_size选项但没有 FFmpeg,会抛出异常终止程序 - 可在
.env中配置FFMPEG_PATH指定安装路径
快速使用
ThinkPHP 控制器中使用
<?php
namespace app\index\controller;
use think\Controller;
use Laobai\CloudStorage\trait\CloudStorageTrait;
class Upload extends Controller
{
use CloudStorageTrait;
// 上传图片 + 缩略图
public function image()
{
$result = $this->upload('image', [
'thumbnail_size' => [300, 300],
]);
return json($result);
}
// 上传视频 + 封面
public function video()
{
$result = $this->upload('video', [
'video_cover_size' => [640, 360],
]);
return json($result);
}
// 上传图片 + 水印
public function watermark()
{
$result = $this->upload('image', [
'watermark' => true,
]);
return json($result);
}
// 上传图片 + 缩略图 + 水印
public function processed()
{
$result = $this->upload('image', [
'thumbnail_size' => [200, 200],
'watermark' => true,
]);
return json($result);
}
// 通用上传(自动识别类型)
public function upload()
{
// 不传选项,什么都不处理,只上传
$result = $this->upload('file');
// 只传字段名,自动识别 image/video/other
return json($result);
}
// 删除文件
public function delete()
{
$this->delete('cloud/20240101/xxx.jpg');
}
}
返回格式(统一)
// 成功
[
'code' => 0,
'msg' => 'success',
'data' => [
'url' => 'https://cdn.example.com/cloud/20240101/xxx.jpg', // 文件地址
'path' => 'cloud/20240101/xxx.jpg', // 存储路径
'type' => 'image', // image/video/other
'size' => 123456, // 文件大小
'mime' => 'image/jpeg', // MIME类型
'ext' => 'jpg', // 扩展名
'thumbnail_url' => '...', // 缩略图地址(图片+thumbnail_size时)
'thumbnail_path' => '...', // 缩略图路径
'cover_url' => '...', // 封面地址(视频+video_cover_size时)
'cover_path' => '...', // 封面路径
'duration' => 0, // 视频时长(秒),仅视频类型返回
]
]
// 失败
[
'code' => 400,
'msg' => '不支持的文件类型: xxx',
'data' => [
'url' => '',
'path' => '',
// ... 其他字段全为空
]
]
完整选项
$result = $this->upload('field_name', [
// ===== 必选 =====
// 无,只需传字段名
// ===== 缩略图(仅图片有效) =====
'thumbnail_size' => [300, 300], // [width, height]
// ===== 视频封面(仅视频有效) =====
'video_cover_size' => [640, 360], // [width, height]
// ===== 水印(仅图片有效) =====
'watermark' => true, // 是否启用水印
// ===== 自定义 =====
'save_path' => 'custom/path/file.jpg', // 自定义保存路径(不含前缀)
'allowed_ext' => ['jpg', 'png', 'gif'], // 允许的扩展名
'max_size' => 5 * 1024 * 1024, // 最大文件大小(字节)
]);
选项说明
| 选项 | 适用类型 | 说明 |
|---|---|---|
thumbnail_size | 图片 | 缩略图尺寸 [width, height],不传则不生成 |
video_cover_size | 视频 | 封面尺寸 [width, height],不传则不生成 |
watermark | 图片 | true 启用水印,false 或不传则不水印 |
save_path | 通用 | 自定义保存路径 |
allowed_ext | 通用 | 允许的扩展名数组 |
max_size | 通用 | 最大文件大小(字节) |
自动处理逻辑
用户上传文件
↓
自动识别类型 (image/video/other)
↓
┌─────────────────────────────────────┐
│ 是图片? │
│ ├─ 有 watermark 选项? → 添加水印 │
│ └─ 有 thumbnail_size? → 生成缩略图 │
├─────────────────────────────────────┤
│ 是视频? │
│ └─ 有 video_cover_size? → 生成封面 │
├─────────────────────────────────────┤
│ 是其他文件? │
│ └─ 直接上传 │
└─────────────────────────────────────┘
↓
返回统一格式
配置说明
在 application/extra/cloud_storage.php:
<?php
return [
'default' => env('CLOUD_STORAGE_DRIVER', 'qiniu'),
// 七牛云配置
'access_key' => env('QINIU_ACCESS_KEY', ''),
'secret_key' => env('QINIU_SECRET_KEY', ''),
'bucket' => env('QINIU_BUCKET', ''),
'domain' => env('QINIU_DOMAIN', ''),
'zone' => env('QINIU_ZONE', 'z0'),
// 本地存储配置
'local_path' => 'uploads/',
'local_url' => '/uploads/',
// 上传配置
'prefix' => 'cloud/',
'upload' => [
'allowed_ext' => ['jpg', 'jpeg', 'png', 'gif', 'mp4', 'pdf'],
'max_size' => 100 * 1024 * 1024,
],
// 缩略图默认配置
'thumbnail' => [
'default_size' => [200, 200],
'quality' => 80,
],
// 视频封面默认配置
'video' => [
'capture_time' => 1, // 截取第几秒
'default_size' => [480, 270], // 默认尺寸
'quality' => 85, // 图片质量
'ffmpeg_path' => env('FFMPEG_PATH', '/usr/bin/ffmpeg'), // FFmpeg 路径
],
// 水印配置
'watermark' => [
'enabled' => false, // 默认不启用
'text' => '',
'font' => '', // 中文字体路径
'size' => 14,
'color' => '#FFFFFF',
'position' => 'bottom-right',
'margin' => 10,
],
];
环境要求
- PHP >= 7.0
- ext-gd
- ext-fileinfo
- FFmpeg(生成视频封面 必需,如果需要
video_cover_size选项)
宝塔面板环境配置
如果使用 宝塔面板,需要进行以下配置:
1. 关闭站点防跨站(open_basedir)
否则组件可能无法正常读取临时文件
- 登录宝塔面板
- 点击 网站 → 选择对应站点 → 设置
- 找到 网站目录 选项卡
- 取消勾选 防跨站攻击(open_basedir)
- 保存
2. 删除 exec 禁用函数
组件需要 exec 函数来执行 FFmpeg 命令生成视频封面
- 登录宝塔面板
- 点击 软件商店 → PHP版本(选择你使用的版本,如 PHP 8.0)
- 点击 禁用函数 设置
- 找到
exec并 删除(点击右侧删除按钮) - 保存
3. 安装 FFmpeg(如果还未安装)
# 方式一:使用宝塔软件商店
# 软件商店 → 搜索 "ffmpeg" → 安装
# 方式二:SSH 终端安装
yum install ffmpeg -y # CentOS
apt install ffmpeg -y # Ubuntu/Debian
项目说明
功能特性
| 功能 | 说明 |
|---|---|
| 云存储集成 | 支持七牛云、本地存储双驱动,可快速扩展其他云存储 |
| 自动识别类型 | 自动识别上传文件类型(图片/视频/其他),智能处理 |
| 图片缩略图 | 上传图片时自动生成指定尺寸的缩略图 |
| 视频封面图 | 上传视频时自动截取指定时间点的画面作为封面 |
| 视频时长 | 上传视频时自动获取并返回视频时长(秒) |
| 文字水印 | 支持文字水印,可配置内容、位置、颜色、大小 |
| 统一返回格式 | 上传结果统一返回格式,调用方无需关心处理细节 |
| 链式配置 | 支持按需配置选项,不传则不处理对应功能 |
| 断点续传 | 支持大文件分片上传,应对网络不稳定场景 |
| FFmpeg 集成 | 自动检测 FFmpeg,缺失时给出友好提示 |
目录结构
laobai/cloud-storage/
├── src/
│ ├── CloudStorage.php # 核心类
│ ├── CloudStorageService.php # ThinkPHP 服务注册
│ ├── ChunkUpload.php # 断点续传
│ ├── helper.php # 助手函数
│ ├── config.php # 默认配置
│ ├── Storage/
│ │ ├── StorageInterface.php # 存储驱动接口
│ │ ├── QiniuStorage.php # 七牛云驱动
│ │ └── LocalStorage.php # 本地存储驱动
│ ├── Exception/
│ │ └── CloudStorageException.php
│ ├── command/
│ │ └── CloudStorageCommand.php
│ └── trait/
│ └── CloudStorageTrait.php
├── examples/ # 使用示例
├── composer.json
└── README.md
使用说明
1. 安装组件
composer require laobai/cloud-storage
2. 配置环境变量
在项目根目录的 .env 文件中添加:
# 选择存储驱动:qiniu / local
CLOUD_STORAGE_DRIVER=qiniu
# 七牛云配置
QINIU_ACCESS_KEY=your_access_key_here
QINIU_SECRET_KEY=your_secret_key_here
QINIU_BUCKET=your_bucket_name
QINIU_DOMAIN=https://your-domain.com
QINIU_ZONE=z0
# FFmpeg 路径(Linux 默认路径,如需生成视频封面必须配置)
FFMPEG_PATH=/usr/bin/ffmpeg
# 水印文字(可选)
WATERMARK_TEXT=© YourWebsite.com
3. ThinkPHP 集成
在控制器中引入 Trait:
<?php
namespace app\index\controller;
use think\Controller;
use Laobai\CloudStorage\trait\CloudStorageTrait;
class Upload extends Controller
{
use CloudStorageTrait;
// 方式一:使用 Trait 方式(推荐)
public function uploadImage()
{
$result = $this->upload('image', [
'thumbnail_size' => [300, 300],
'watermark' => true,
]);
return json($result);
}
// 方式二:直接实例化
public function uploadVideo()
{
$cloud = \Laobai\CloudStorage\CloudStorage::init();
$result = $cloud->upload($this->request, 'video', [
'video_cover_size' => [640, 360],
]);
return json($result);
}
}
4. 基础用法示例
// 简单上传(自动识别类型)
$result = $this->upload('file');
// 上传图片 + 生成缩略图
$result = $this->upload('avatar', [
'thumbnail_size' => [200, 200],
]);
// 上传图片 + 添加水印
$result = $this->upload('image', [
'watermark' => true,
]);
// 上传视频 + 生成封面
$result = $this->upload('video', [
'video_cover_size' => [640, 360],
]);
// 上传图片 + 缩略图 + 水印
$result = $this->upload('photo', [
'thumbnail_size' => [400, 400],
'watermark' => true,
]);
// 自定义保存路径
$result = $this->upload('file', [
'save_path' => 'avatars/user_' . $userId . '.jpg',
]);
// 自定义允许类型和大小
$result = $this->upload('file', [
'allowed_ext' => ['jpg', 'png'],
'max_size' => 5 * 1024 * 1024, // 5MB
]);
5. 删除文件
// 删除单个文件
$result = $this->delete('cloud/20240101/abc123.jpg');
// 批量删除
$result = $this->deleteMultiple([
'cloud/20240101/abc123.jpg',
'cloud/20240101/thumb_200x200.jpg',
]);
6. 处理返回结果
$result = $this->upload('image', [
'thumbnail_size' => [300, 300],
]);
if ($result['code'] === 0) {
$data = $result['data'];
echo '文件地址:' . $data['url'];
echo '存储路径:' . $data['path'];
echo '文件类型:' . $data['type']; // image/video/other
echo '文件大小:' . $data['size'];
echo '缩略图地址:' . $data['thumbnail_url']; // 有则返回,无则空
echo '视频封面:' . $data['cover_url']; // 有则返回,无则空
echo '视频时长:' . $data['duration']; // 视频时长(秒),仅视频类型返回
} else {
echo '上传失败:' . $result['msg'];
}
高级用法
自定义配置
$result = $this->upload('image', [
// 缩略图配置
'thumbnail_size' => [300, 300],
'thumbnail_quality' => 80, // 可选,默认 80
// 视频封面配置
'video_cover_size' => [640, 360],
'video_capture_time' => 2, // 截取第几秒,默认 1
// 水印配置
'watermark' => true,
'watermark_text' => '© MySite',
'watermark_position' => 'bottom-right',
'watermark_color' => '#FFFFFF',
'watermark_size' => 16,
'watermark_margin' => 10,
// 文件验证
'allowed_ext' => ['jpg', 'jpeg', 'png'],
'max_size' => 10 * 1024 * 1024,
// 存储配置
'save_path' => 'custom/path/file.jpg',
]);
使用原生 PHP(非 ThinkPHP)
<?php
require_once __DIR__ . '/vendor/autoload.php';
use Laobai\CloudStorage\CloudStorage;
// 初始化
$cloud = CloudStorage::init([
'default' => 'qiniu',
'access_key' => 'your_access_key',
'secret_key' => 'your_secret_key',
'bucket' => 'your_bucket',
'domain' => 'https://cdn.example.com',
]);
// 直接上传本地文件
$result = $cloud->uploadFile('/path/to/local/file.jpg', [
'thumbnail_size' => [200, 200],
]);
print_r($result);
常见问题
Q: 上传视频报 "FFmpeg 未安装" 错误?
A: 这是因为你传了 video_cover_size 选项,需要 FFmpeg 来生成视频封面。解决方案:
- 安装 FFmpeg:
apt install ffmpeg - 或者在
.env中配置正确的 FFmpeg 路径:FFMPEG_PATH=/usr/local/bin/ffmpeg - 如果不需要封面,不传
video_cover_size选项即可
Q: 水印文字显示乱码?
A: 水印默认使用系统字体,不支持中文。需要配置中文字体文件:
'watermark' => [
'font' => '/path/to/chinese_font.ttf', // 使用支持中文的 TTF 字体
'text' => '你的网站名',
],
Q: 如何切换到本地存储?
A: 在 .env 中修改:
CLOUD_STORAGE_DRIVER=local
STORAGE_LOCAL_PATH=/var/www/uploads/
STORAGE_LOCAL_URL=https://your-domain.com/uploads/
Q: 支持哪些图片格式?
A: 支持:jpg、jpeg、png、gif、bmp、webp、svg
Q: 支持哪些视频格式?
A: 支持:mp4、avi、mov、wmv、flv、mkv、3gp
更新日志
v1.1.0 (2026-05-11)
- 新增视频时长获取功能
- 上传视频时自动返回视频时长(秒)
v1.0.0 (2026-05-11)
- 首发版本
- 支持七牛云、本地存储双驱动
- 支持图片缩略图、视频封面、文字水印
- 统一返回格式
- FFmpeg 集成与检测
联系作者
- 作者:别知己
- 邮箱:369758482@qq.com
如有问题或建议,欢迎邮件联系!
License
MIT
统计信息
- 总下载量: 5
- 月度下载量: 0
- 日度下载量: 0
- 收藏数: 0
- 点击次数: 8
- 依赖项目数: 0
- 推荐数: 0
其他信息
- 授权协议: MIT
- 更新时间: 2026-05-11