必须通过flysystem抽象层配置与调用:先安装league/flysystem及对应云适配器(如七牛用overtrue/flysystem-qiniu),再在config/filesystem.php中定义磁盘,上传时用$file->getrealpath()或$file->read()获取内容,大文件需直连云sdk分片上传,关键操作须用writestream、临时名move等保障安全。

如果您在ThinkPHP项目中需要统一管理本地与云存储的文件操作,则必须通过Flysystem抽象层进行配置与调用。以下是完成Flysystem存储配置与使用的具体步骤:
一、安装Flysystem核心库及对应云存储适配器
Flysystem本身不内置任何云存储驱动,需按需安装官方或社区维护的适配器包。不同云服务需匹配专用扩展,避免使用已废弃组件。
1、执行Composer命令安装Flysystem基础库:composer require league/flysystem
2、根据目标存储类型选择并安装对应适配器:七牛云请用 overtrue/flysystem-qiniu;阿里云OSS请用 overtrue/flysystem-oss;腾讯云COS请用 overtrue/flysystem-cos;亚马逊S3请用 league/flysystem-aws-s3-v3
3、若使用ThinkPHP 6.x/7.x,确保未安装已废弃的 league/flysystem-qiniu —— 它会导致鉴权失败与bucket校验不通过。
二、配置filesystem.php磁盘定义
配置文件位于 config/filesystem.php,需在 disks 数组中声明各存储磁盘。每个磁盘必须指定 type(对应适配器类名小写)、必要凭证参数及行为控制项。
1、定义本地磁盘示例:'local' => ['type' => 'local', 'root' => app()->getRuntimePath() . 'storage']
2、定义七牛云磁盘时,bucket名必须全小写且不含-z1等区域后缀;accessKey/secretKey须从七牛控制台「密钥管理」复制;region参数填z1/z2等正确区域码;useHttps设为true
3、定义阿里云OSS磁盘时,endpoint必须带https://前缀;is_cname设为true当使用自定义CDN域名;region参数不可填AWS风格如cn-hangzhou,应为空字符串或oss-cn-hangzhou
三、上传文件时正确处理think\File对象
ThinkPHP的$request->file()返回的是think\File实例,非原生SplFileInfo,不能直接传入Flysystem方法。错误传递将导致File not found或空文件写入。
1、获取临时文件真实路径:$file->getRealPath()
2、读取二进制内容:file_get_contents($file->getRealPath())
3、若getRealPath()返回false(如启用Swoole或OPcache),fallback调用:$file->read()
4、禁止使用$file->getPathname()或$file本身作为put参数——该路径受open_basedir限制且Flysystem无法识别。
四、大文件分片上传绕过Flysystem直连SDK
Flysystem不支持断点续传与分片逻辑,>10MB文件上传易超时或内存溢出。此时应放弃put()方法,改用云厂商原生SDK实现底层控制。
1、七牛云场景:引入qiniu/php-sdk v7+,使用Qiniu\Storage\ResumeUploader类执行分片上传
2、阿里云OSS场景:使用aliyuncs/oss-sdk-php中的OssClient::multiuploadFile()方法
3、腾讯云COS场景:调用cos-php-sdk-v5的UploadPartCopyRequest或分块上传接口
4、所有分片上传均需自行管理上传ID、Etag校验及最终CompleteMultipartUpload调用。
五、安全写入与目录列表关键避坑
Flysystem不是黑盒,其write()无完整性校验、listContents()默认不递归、replace()非原子操作——这些特性在生产环境极易引发数据异常。
1、替代write():使用writeStream()并传入fopen($path, 'rb')流,避免内存拼接
2、验证写入结果:写入后立即调用read()或fileSize()轻量校验(S3的fileSize()为HEAD请求,开销低)
3、获取完整目录列表:调用listContents()时显式传入第二个参数true表示递归,并确认适配器支持directory_listing选项
4、替换关键文件:先write()至临时名(如temp_{$uniqid}.json),再move()覆盖目标名——本地为原子rename,云存储为copy+delete组合操作。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











