<?php
* @Descripttion: 七牛云存储服务
* @version: v1
* @Author: youhujun youhu8888@163.com
* @Date: 2026-01-08 00:01:25
* @LastEditors: youhujun youhu8888@163.com
* @LastEditTime: 2026-01-08 00:01:25
* @FilePath: App.Service.V1.Store.QiNiuFacadeService.php
* Copyright (C) 2026 youhujun. All rights reserved.
*/
namespace YouHuJun\Tool\App\Services\V1\Store;
use YouHuJun\Tool\App\Exceptions\CommonException;
use Qiniu\Auth as QiniuAuth;
use Qiniu\Storage\UploadManager;
use Qiniu\Storage\BucketManager;
* 七牛云存储服务类
*
* 提供七牛云文件上传和下载链接生成功能
* 注意: 此服务依赖七牛云官方SDK (qiniu/php-sdk)
*/
class QiNiuFacadeService
{
* 七牛云AccessKey
*
* @var string
*/
private string $accessKey;
* 七牛云SecretKey
*
* @var string
*/
private string $secretKey;
* 存储空间名称
*
* @var string
*/
private string $bucket;
* 七牛云认证对象
*
* @var QiniuAuth
*/
private $auth;
* 上传凭证
*
* @var string
*/
private string $uploadToken;
* CDN域名
*
* @var string
*/
private string $cdnUrl;
* 上传凭证有效期(秒),默认2小时
*
* @var int
*/
private int $expires = 7200;
* 自定义返回内容
*
* @var string|null
*/
private ?string $returnBody = null;
* 构造函数
*
* @param string $accessKey 七牛云AccessKey
* @param string $secretKey 七牛云SecretKey
* @param string|null $cdnUrl CDN域名,可选
* @param int $expires 上传凭证有效期(秒)
* @throws CommonException
*/
public function __construct(string $accessKey, string $secretKey, ?string $cdnUrl = null, int $expires = 7200)
{
if (empty($accessKey)) {
throw new CommonException('QiNiuAccessKeyError');
}
if (empty($secretKey)) {
throw new CommonException('QiNiuSecretKeyError');
}
$this->accessKey = $accessKey;
$this->secretKey = $secretKey;
$this->cdnUrl = $cdnUrl ?? '';
$this->expires = $expires;
$this->auth = new QiniuAuth($accessKey, $secretKey);
$this->returnBody = '{"key":"$(key)","hash":"$(etag)","fsize":$(fsize),"name":"$(fname)"}';
}
* 设置CDN域名
*
* @param string $cdnUrl
* @return void
*/
public function setCdnUrl(string $cdnUrl): void
{
$this->cdnUrl = $cdnUrl;
}
* 设置上传凭证有效期
*
* @param int $seconds 有效期(秒)
* @return void
*/
public function setExpires(int $seconds): void
{
$this->expires = $seconds;
}
* 设置自定义返回内容
*
* @param string $returnBody JSON格式的返回内容
* @return void
*/
public function setReturnBody(string $returnBody): void
{
$this->returnBody = $returnBody;
}
* 获取上传凭证
*
* @param string $bucket 存储空间名称
* @param string|null $keyToOverwrite 覆盖上传的文件名,不传则不覆盖
* @return string 上传凭证
* @throws CommonException
*/
protected function getUploadToken(string $bucket, ?string $keyToOverwrite = null): string
{
if (empty($bucket)) {
throw new CommonException('QiNiuBucketError');
}
$this->bucket = $bucket;
$policy = [
'returnBody' => $this->returnBody
];
$this->uploadToken = $this->auth->uploadToken(
$bucket,
$keyToOverwrite,
$this->expires,
$policy,
true
);
return $this->uploadToken;
}
* 上传文件到七牛云
*
* @param string $filePath 本地文件路径
* @param string $bucket 存储空间名称
* @param string $savePath 保存路径(文件key)
* @param string|null $mimeType MIME类型,默认 application/octet-stream
* @param bool $checkCrc 是否校验CRC32,默认true
* @return array 返回上传结果
* @throws CommonException
*/
public function uploadFile(string $filePath, string $bucket, string $savePath, ?string $mimeType = null, bool $checkCrc = true): array
{
if (!file_exists($filePath)) {
throw new CommonException('QiNiuFileNotFoundError');
}
$this->getUploadToken($bucket);
$uploadMgr = new UploadManager();
$mimeType = $mimeType ?? 'application/octet-stream';
list($result, $error) = $uploadMgr->putFile(
$this->uploadToken,
$savePath,
$filePath,
null,
$mimeType,
$checkCrc,
null,
'v2'
);
if ($error !== null) {
throw new CommonException('QiNiuUploadFileError');
}
return $result;
}
* 上传文件内容(二进制数据)
*
* @param string $data 文件内容
* @param string $bucket 存储空间名称
* @param string $savePath 保存路径(文件key)
* @param string|null $mimeType MIME类型
* @return array 返回上传结果
* @throws CommonException
*/
public function uploadData(string $data, string $bucket, string $savePath, ?string $mimeType = null): array
{
if (empty($data)) {
throw new CommonException('QiNiuUploadDataEmpty');
}
$this->getUploadToken($bucket);
$uploadMgr = new UploadManager();
$mimeType = $mimeType ?? 'application/octet-stream';
list($result, $error) = $uploadMgr->put(
$this->uploadToken,
$savePath,
$data,
null,
$mimeType
);
if ($error !== null) {
throw new CommonException('QiNiuUploadDataError');
}
return $result;
}
* 获取私有空间下载链接
*
* @param string $savePath 保存路径(文件key)
* @param int|null $expires 有效期(秒),不传则使用默认值3600秒
* @return string 签名后的下载链接
* @throws CommonException
*/
public function getPrivateFileUrl(string $savePath, ?int $expires = null): string
{
if (empty($this->cdnUrl)) {
throw new CommonException('QiNiuCdnUrlError');
}
if (empty($savePath)) {
throw new CommonException('QiNiuFilePathEmpty');
}
$baseUrl = $this->cdnUrl . $savePath;
$expires = $expires ?? 3600;
$signedUrl = $this->auth->privateDownloadUrl($baseUrl, $expires);
return $signedUrl;
}
* 获取公有空间下载链接
*
* @param string $savePath 保存路径(文件key)
* @return string 下载链接
* @throws CommonException
*/
public function getPublicFileUrl(string $savePath): string
{
if (empty($this->cdnUrl)) {
throw new CommonException('QiNiuCdnUrlError');
}
if (empty($savePath)) {
throw new CommonException('QiNiuFilePathEmpty');
}
$baseUrl = $this->cdnUrl . $savePath;
return $baseUrl;
}
* 删除文件
*
* @param string $bucket 存储空间名称
* @param string $savePath 文件key
* @return bool 删除成功返回true
* @throws CommonException
*/
public function deleteFile(string $bucket, string $savePath): bool
{
if (empty($bucket)) {
throw new CommonException('QiNiuBucketError');
}
if (empty($savePath)) {
throw new CommonException('QiNiuFilePathEmpty');
}
$bucketMgr = new BucketManager($this->auth);
$error = $bucketMgr->delete($bucket, $savePath);
if ($error !== null) {
throw new CommonException('QiNiuDeleteFileError');
}
return true;
}
* 获取文件信息
*
* @param string $bucket 存储空间名称
* @param string $savePath 文件key
* @return array 文件信息
* @throws CommonException
*/
public function getFileInfo(string $bucket, string $savePath): array
{
if (empty($bucket)) {
throw new CommonException('QiNiuBucketError');
}
if (empty($savePath)) {
throw new CommonException('QiNiuFilePathEmpty');
}
$bucketMgr = new BucketManager($this->auth);
list($fileInfo, $error) = $bucketMgr->stat($bucket, $savePath);
if ($error !== null) {
throw new CommonException('QiNiuGetFileInfoError');
}
return $fileInfo;
}
* 获取上传凭证(供客户端使用)
*
* @param string $bucket 存储空间名称
* @param string|null $keyToOverwrite 覆盖上传的文件名
* @return string 上传凭证
* @throws CommonException
*/
public function getUploadTokenForClient(string $bucket, ?string $keyToOverwrite = null): string
{
return $this->getUploadToken($bucket, $keyToOverwrite);
}
}