Looking to hire Laravel developers? Try LaraJobs

laravel-flysystem-tos maintained by larva

Description
This is a Flysystem adapter for the volcengine TOS.
Last update
2026/07/24 08:32 (dev-master)
License
Links
Downloads
846

Comments
comments powered by Disqus

Laravel Flysystem TOS

适用于 Laravel 的火山引擎 TOS(对象存储)Flysystem 适配器,完整支持火山引擎 TOS 所有方法和操作。

要求

  • PHP >= 8.2
  • Laravel >= 12.0

安装

composer require larva/laravel-flysystem-tos

该包支持 Laravel 包自动发现(Package Auto-Discovery),无需手动注册服务提供者。

配置

config/filesystems.phpdisks 中添加 TOS 磁盘配置:

'tos' => [
    'driver'        => 'tos',
    'access_key'    => env('TOS_ACCESS_KEY'),
    'access_secret' => env('TOS_ACCESS_SECRET'),
    'bucket'        => env('TOS_BUCKET'),
    'region'        => env('TOS_REGION'), // 例如 cn-beijing
    'endpoint'      => env('TOS_ENDPOINT'), // TOS 接入域名,不要使用 CName
    'url'           => env('TOS_URL'), // CDN 或自定义域名,末尾不要斜杠
    'root'          => env('TOS_ROOT', ''), // 存储路径前缀
    'visibility'    => 'public', // 默认可见性:public 或 private
    'ssl'           => true, // 是否使用 HTTPS
    'throw'         => false,
    'report'        => false,
],

.env 文件中配置对应的环境变量:

TOS_ACCESS_KEY=your-access-key
TOS_ACCESS_SECRET=your-access-secret
TOS_BUCKET=your-bucket
TOS_REGION=cn-beijing
TOS_ENDPOINT=tos-cn-beijing.volces.com
TOS_URL=https://cdn.example.com  # 可选,CDN 或自定义域名
TOS_ROOT=uploads                 # 可选,存储路径前缀

提示:如果未配置 access_keyaccess_secret,将使用 TOS SDK 的环境凭证方式(基于 TOS_ACCESS_KEY / TOS_ACCESS_SECRET 环境变量或 IAM 角色临时凭证)。

如需将 TOS 设为默认存储驱动,修改 default 配置:

'default' => 'tos',

使用

基本文件操作

use Illuminate\Support\Facades\Storage;

// 获取磁盘实例
$disk = Storage::disk('tos');

// 写入文件
$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}://{bucket}.{endpoint}/{path} 格式
    • private:生成 5 分钟有效期的临时 URL
// 获取文件 URL
$url = Storage::disk('tos')->url('path/to/file.txt');

// 获取文件可见性
$visibility = Storage::disk('tos')->getVisibility('path/to/file.txt');

// 设置文件可见性
Storage::disk('tos')->setVisibility('path/to/file.txt', 'private');

临时 URL

use Carbon\Carbon;

// 生成临时下载 URL(默认 5 分钟,可自定义)
$tempUrl = Storage::disk('tos')->temporaryUrl(
    'path/to/private-file.txt',
    Carbon::now()->addMinutes(30)
);

// 生成临时上传 URL
$result = Storage::disk('tos')->temporaryUploadUrl(
    'path/to/upload.txt',
    Carbon::now()->addMinutes(10)
);
// $result['url']     — 上传 URL
// $result['headers'] — 上传所需的请求头

获取 TOS 客户端

如需直接调用 TOS SDK 的完整功能,可获取底层客户端实例:

use Larva\Flysystem\Volc\TOSAdapter;

/** @var TOSAdapter $adapter */
$adapter = Storage::disk('tos')->getAdapter();
$client = $adapter->getClient(); // Tos\TosClient 实例

签名 URL

$adapter = Storage::disk('tos')->getAdapter();

// 生成签名 URL,可指定 HTTP 方法和备用 endpoint
$signedUrl = $adapter->signUrl('path/to/file.txt', 3600, [], 'GET');

前端直传:使用预签名 URL 上传

在 Web 应用中,通常需要让浏览器直接上传文件到 TOS,而不经过服务器中转。通过后端生成预签名 URL,前端使用 TOS Browser.js SDKaxios 即可实现直传。

这种方式的优势是 AccessKey 不会暴露给前端,且文件无需经过应用服务器。

后端:生成预签名上传 URL

定义一个 API 路由,返回预签名 URL:

// routes/api.php
use Illuminate\Support\Facades\Storage;
use Carbon\Carbon;

Route::post('/tos/upload-url', function (\Illuminate\Http\Request $request) {
    $request->validate([
        'filename' => 'required|string',
    ]);

    $path = 'uploads/' . $request->input('filename');

    $result = Storage::disk('tos')->temporaryUploadUrl(
        $path,
        Carbon::now()->addMinutes(10)
    );

    return response()->json([
        'url'     => $result['url'],
        'headers' => $result['headers'],
        'path'    => $path,
    ]);
});

前端:使用 axios 上传

<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/1.4.0/axios.min.js"></script>
<script>
async function uploadToTOS(file) {
    // 1. 从后端获取预签名 URL
    const { data } = await axios.post('/api/tos/upload-url', {
        filename: file.name,
    });

    // 2. 使用预签名 URL 直接上传到 TOS
    await axios.put(data.url, file, {
        headers: data.headers,
    });

    console.log('上传成功,文件路径:', data.path);
}
</script>

前端:使用 TOS Browser.js SDK 上传

如果不使用预签名 URL,也可以通过 STS 临时凭证初始化 TOS Client,直接在浏览器端生成预签名 URL 并上传:

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8" />
    <title>TOS 直传示例</title>
    <!-- 导入 TOS Browser.js SDK -->
    <script src="https://tos-public.volccdn.com/obj/volc-tos-public/@volcengine/tos-sdk@latest/browser/tos.umd.production.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>
        // 从后端 STS 接口获取临时凭证(推荐)
        const client = new TOS({
            region: 'cn-beijing',           // Bucket 所在地域
            endpoint: 'tos-cn-beijing.volces.com',
            accessKeyId: 'your-sts-ak',     // STS 临时 AccessKey ID
            accessKeySecret: 'your-sts-sk', // STS 临时 AccessKey Secret
            stsToken: 'your-sts-token',     // STS 安全令牌
            bucket: 'your-bucket',
        });

        async function upload() {
            const file = document.getElementById('fileInput').files[0];
            if (!file) return;

            const objectName = 'uploads/' + file.name;

            // 生成预签名上传 URL
            const url = client.getPreSignedUrl({
                method: 'PUT',
                bucket: 'your-bucket',
                key: objectName,
            });

            // 使用预签名 URL 上传文件
            const uploadResult = await axios.put(url, file);
            console.log('上传成功,状态码:', uploadResult.status);
        }
    </script>
</body>
</html>

安全提示:Browser.js SDK 方式需要在前端暴露临时凭证,请务必通过 STS 服务获取临时凭证而非直接使用永久 AccessKey。推荐使用后端生成预签名 URL 的方式,前端无需任何凭证。

关于 endpoint 配置

endpoint 应使用 TOS 接入域名(如 tos-cn-beijing.volces.com),不要使用 CName。如需使用自定义域名或 CDN,请通过 url 配置项指定。

相关文档

License

MIT