larva / laravel-flysystem-kodo
This is a Flysystem adapter for the Qiniu Kodo.
Requires
- php: ^8.2
- laravel/framework: ^12.0 | ^13.0
- larva/flysystem-kodo: ^1.0
- league/flysystem: ^3.0
Requires (Dev)
This package is auto-updated.
Last update: 2026-07-24 07:52:37 UTC
README
适用于 Laravel 的七牛 Kodo(对象存储)Flysystem 适配器,完整支持七牛 Kodo 所有方法和操作。
要求
- PHP >= 8.2
- Laravel 12.x / 13.x
- League Flysystem ^3.0
安装
composer require larva/laravel-flysystem-kodo
该包支持 Laravel 包自动发现(Package Auto-Discovery),无需手动注册服务提供者。
配置
在 config/filesystems.php 的 disks 中添加 Kodo 磁盘配置:
'kodo' => [ 'driver' => 'kodo', 'access_key' => env('QINIU_ACCESS_KEY'), 'secret_key' => env('QINIU_SECRET_KEY'), 'bucket' => env('QINIU_BUCKET'), 'url' => env('QINIU_BUCKET_URL'), // CDN 或自定义域名,末尾不要斜杠,如 https://cdn.example.com 'root' => env('QINIU_ROOT', ''), // 存储路径前缀,可选 'is_custom_domain' => false, // 如果 endpoint 是绑定的自定义域名,设置为 true,同时 url 设置无效 'endpoint' => env('QINIU_ENDPOINT', ''), // 自定义域名(当 is_custom_domain 为 true 时使用) 'ssl' => true, // 是否使用 HTTPS 'upload_url' => env('QINIU_UPLOAD_URL', 'https://upload.qiniup.com'), // 上传端点,可选 'visibility' => 'public', // 默认文件可见性:public 或 private 'directory_visibility' => 'public', // 默认目录可见性:public 或 private,可选 'options' => [], // 传递给底层 Kodo 适配器的额外选项,可选 'throw' => false, 'report' => false, ],
在 .env 文件中配置对应的环境变量:
QINIU_ACCESS_KEY=your-access-key QINIU_SECRET_KEY=your-secret-key QINIU_BUCKET=your-bucket QINIU_BUCKET_URL=https://cdn.example.com # CDN 或自定义域名 QINIU_ROOT=uploads # 可选,存储路径前缀
如需将 Kodo 设为默认存储驱动,修改 default 配置:
'default' => 'kodo',
使用
基本文件操作
use Illuminate\Support\Facades\Storage; // 获取磁盘实例 $disk = Storage::disk('kodo'); // 写入文件 $disk->put('path/to/file.txt', 'file contents'); // 读取文件 $contents = $disk->get('path/to/file.txt'); // 检查文件是否存在 $exists = $disk->exists('path/to/file.txt'); // 删除文件 $disk->delete('path/to/file.txt'); // 复制文件 $disk->copy('source/path.txt', 'dest/path.txt'); // 移动文件 $disk->move('source/path.txt', 'dest/path.txt'); // 列出目录内容 $files = $disk->files('directory'); $allFiles = $disk->allFiles('directory');
文件上传
// 上传文件 $path = $disk->putFile('uploads', $request->file('avatar')); // 上传文件并指定可见性 $path = $disk->putFile('uploads', $request->file('avatar'), 'public');
获取文件 URL
URL 生成遵循以下优先级:
- 若配置了
url(CDN/自定义域名),使用该地址拼接 - 否则根据文件可见性判断:
- public:使用
{scheme}://{domain}/{path}格式 - private:生成 5 分钟有效期的临时下载 URL
- public:使用
// 获取文件 URL $url = Storage::disk('kodo')->url('path/to/file.txt'); // 获取文件可见性 $visibility = Storage::disk('kodo')->getVisibility('path/to/file.txt'); // 设置文件可见性 Storage::disk('kodo')->setVisibility('path/to/file.txt', 'private');
临时 URL
use Carbon\Carbon; // 生成临时下载 URL(默认 5 分钟,可自定义) $tempUrl = Storage::disk('kodo')->temporaryUrl( 'path/to/private-file.txt', Carbon::now()->addMinutes(30) ); // 生成临时上传 URL $result = Storage::disk('kodo')->temporaryUploadUrl( 'path/to/upload.txt', Carbon::now()->addMinutes(10) ); // $result['url'] — 上传端点 URL(如 https://upload.qiniup.com) // $result['headers'] — 上传请求所需的 Authorization 头(包含上传凭证)
获取 Kodo 客户端
如需直接调用七牛 SDK 的完整功能,可获取底层 Auth 实例:
use Larva\Flysystem\Qiniu\KodoAdapter; /** @var KodoAdapter $adapter */ $adapter = Storage::disk('kodo')->getAdapter(); $auth = $adapter->getClient(); // Qiniu\Auth 实例
前端直传:使用上传凭证上传
在 Web 应用中,通常需要让浏览器直接上传文件到七牛 Kodo,而不经过服务器中转。通过后端生成上传凭证,前端使用七牛 JavaScript SDK 或 axios 即可实现直传。
这种方式的优势是 AccessKey 不会暴露给前端,且文件无需经过应用服务器。
后端:生成上传凭证
定义一个 API 路由,返回上传凭证:
// routes/api.php use Illuminate\Support\Facades\Storage; use Carbon\Carbon; Route::post('/kodo/upload-url', function (\Illuminate\Http\Request $request) { $request->validate([ 'filename' => 'required|string', ]); $path = 'uploads/' . $request->input('filename'); $result = Storage::disk('kodo')->temporaryUploadUrl( $path, Carbon::now()->addMinutes(10) ); return response()->json([ 'url' => $result['url'], 'headers' => $result['headers'], 'path' => $path, ]); });
前端:使用 axios 上传
七牛 Kodo 使用表单上传方式,需要通过 FormData 提交文件:
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/1.4.0/axios.min.js"></script> <script> async function uploadToKodo(file) { // 1. 从后端获取上传凭证 const { data } = await axios.post('/api/kodo/upload-url', { filename: file.name, }); // 2. 使用 FormData 构造上传请求 const formData = new FormData(); formData.append('key', data.path); formData.append('file', file); // 3. 上传到七牛 await axios.post(data.url, formData, { headers: { ...data.headers, 'Content-Type': 'multipart/form-data', }, }); console.log('上传成功,文件路径:', data.path); } </script>
前端:使用七牛 JavaScript SDK 上传
也可以通过七牛官方 JavaScript SDK 进行上传:
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8" /> <title>Kodo 直传示例</title> <!-- 导入七牛 JavaScript SDK --> <script src="https://cdnjs.cloudflare.com/ajax/libs/qiniu-js/3.4.2/qiniu.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/axios/1.4.0/axios.min.js"></script> </head> <body> <input type="file" id="fileInput" /> <button onclick="upload()">上传</button> <script> async function upload() { const file = document.getElementById('fileInput').files[0]; if (!file) return; // 从后端获取上传凭证 const { data } = await axios.post('/api/kodo/upload-url', { filename: file.name, }); // 使用上传凭证创建七牛上传对象 const observable = qiniu.upload( file, data.path, data.headers['Authorization'].replace('UpToken ', '') ); observable.subscribe({ next(res) { console.log('上传进度:', res.total.percent + '%'); }, error(err) { console.error('上传失败:', err); }, complete(res) { console.log('上传成功:', res); } }); } </script> </body> </html>
安全提示:前端直传方式使用的是后端生成的临时上传凭证,AccessKey 不会暴露给前端。上传凭证可以设置过期时间和上传策略限制(如文件大小、MIME 类型等)。
关于 url 配置
url 应使用七牛存储空间绑定的域名(CDN 或自定义域名),如 https://cdn.example.com。
如果使用自定义域名作为 endpoint,可设置 is_custom_domain 为 true,此时将自动从 endpoint 生成 url:
'kodo' => [ 'driver' => 'kodo', 'access_key' => env('QINIU_ACCESS_KEY'), 'secret_key' => env('QINIU_SECRET_KEY'), 'bucket' => env('QINIU_BUCKET'), 'endpoint' => env('QINIU_ENDPOINT'), // 自定义域名,如 cdn.example.com 'is_custom_domain' => true, 'ssl' => true, // ... ],
开发
代码风格检查
本项目使用 PHP-CS-Fixer 统一代码风格。
# 检查代码风格(仅报告,不修改) composer check-style # 自动修复代码风格问题 composer fix-style