larva/laravel-flysystem-kodo

This is a Flysystem adapter for the Qiniu Kodo.

Maintainers

Package info

github.com/larva-cool/laravel-flysystem-kodo

pkg:composer/larva/laravel-flysystem-kodo

Transparency log

Statistics

Installs: 1

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

2.1.0 2026-07-24 07:51 UTC

This package is auto-updated.

Last update: 2026-07-24 07:52:37 UTC


README

Stable Version Total Downloads License

适用于 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.phpdisks 中添加 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 生成遵循以下优先级:

  1. 若配置了 url(CDN/自定义域名),使用该地址拼接
  2. 否则根据文件可见性判断:
    • public:使用 {scheme}://{domain}/{path} 格式
    • private:生成 5 分钟有效期的临时下载 URL
// 获取文件 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_domaintrue,此时将自动从 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

相关文档

License

MIT