PHP七牛云上传凭证生成

wen PHP项目 2

本文目录导读:

PHP七牛云上传凭证生成

  1. 基础版(单文件上传凭证)
  2. 完整版(包含多种上传场景)
  3. 使用官方SDK(推荐)
  4. 前端集成示例

基础版(单文件上传凭证)

<?php
class QiniuToken
{
    private $accessKey;
    private $secretKey;
    private $bucket;
    public function __construct($accessKey, $secretKey, $bucket)
    {
        $this->accessKey = $accessKey;
        $this->secretKey = $secretKey;
        $this->bucket = $bucket;
    }
    /**
     * 生成上传凭证
     * @param string $key 上传的文件名(可选)
     * @param int $expires 有效期(秒)
     * @param array $policy 其他策略
     * @return string
     */
    public function generateToken($key = null, $expires = 3600, $policy = [])
    {
        // 1. 构建上传策略
        $deadline = time() + $expires;
        $policy = array_merge([
            'scope' => $this->bucket . ($key ? ':' . $key : ''),
            'deadline' => $deadline
        ], $policy);
        // 2. 对策略进行JSON编码并base64
        $encodedPolicy = $this->base64UrlEncode(json_encode($policy));
        // 3. 使用SecretKey对编码后的策略进行HMAC-SHA1签名
        $sign = hash_hmac('sha1', $encodedPolicy, $this->secretKey, true);
        // 4. 将签名进行base64编码
        $encodedSign = $this->base64UrlEncode($sign);
        // 5. 拼接上传凭证
        return $this->accessKey . ':' . $encodedSign . ':' . $encodedPolicy;
    }
    /**
     * Base64 URL安全编码
     */
    private function base64UrlEncode($data)
    {
        return str_replace(['+', '/'], ['-', '_'], base64_encode($data));
    }
}
// 使用示例
$qiniu = new QiniuToken(
    'YOUR_ACCESS_KEY',
    'YOUR_SECRET_KEY',
    'YOUR_BUCKET_NAME'
);
// 生成普通上传凭证
$token = $qiniu->generateToken();
echo $token;
?>

完整版(包含多种上传场景)

<?php
class QiniuTokenManager
{
    private $accessKey;
    private $secretKey;
    private $bucket;
    public function __construct($accessKey, $secretKey, $bucket)
    {
        $this->accessKey = $accessKey;
        $this->secretKey = $secretKey;
        $this->bucket = $bucket;
    }
    /**
     * 普通上传凭证
     */
    public function simpleUploadToken($key = null, $expires = 3600)
    {
        $policy = [
            'scope' => $this->bucket . ($key ? ':' . $key : ''),
            'deadline' => time() + $expires
        ];
        return $this->createToken($policy);
    }
    /**
     * 覆盖上传凭证(同名覆盖)
     */
    public function overwriteUploadToken($key, $expires = 3600)
    {
        $policy = [
            'scope' => $this->bucket . ':' . $key,
            'deadline' => time() + $expires,
            'insertOnly' => 0 // 允许覆盖
        ];
        return $this->createToken($policy);
    }
    /**
     * 限定上传内容类型
     */
    public function mimeLimitToken($mimeTypes, $key = null, $expires = 3600)
    {
        $policy = [
            'scope' => $this->bucket . ($key ? ':' . $key : ''),
            'deadline' => time() + $expires,
            'mimeLimit' => $mimeTypes // 如: 'image/*;text/plain'
        ];
        return $this->createToken($policy);
    }
    /**
     * 生成带回调的上传凭证
     */
    public function callbackToken($callbackUrl, $callbackBody = null, $key = null, $expires = 3600)
    {
        $policy = [
            'scope' => $this->bucket . ($key ? ':' . $key : ''),
            'deadline' => time() + $expires,
            'callbackUrl' => $callbackUrl,
            'callbackBody' => $callbackBody ?: 'key=$(key)&hash=$(etag)&fsize=$(fsize)',
            'callbackBodyType' => 'application/x-www-form-urlencoded'
        ];
        return $this->createToken($policy);
    }
    /**
     * 生成带持久化处理的上传凭证
     */
    public function persistentToken($persistentOps, $persistentNotifyUrl, $key = null, $expires = 3600)
    {
        $policy = [
            'scope' => $this->bucket . ($key ? ':' . $key : ''),
            'deadline' => time() + $expires,
            'persistentOps' => $persistentOps, // 如: 'avthumb/mp4/ab/160k'
            'persistentNotifyUrl' => $persistentNotifyUrl
        ];
        return $this->createToken($policy);
    }
    /**
     * 创建上传凭证核心方法
     */
    private function createToken($policy)
    {
        // 对策略进行JSON编码并base64
        $encodedPolicy = $this->base64UrlEncode(json_encode($policy));
        // 使用SecretKey进行HMAC-SHA1签名
        $sign = hash_hmac('sha1', $encodedPolicy, $this->secretKey, true);
        $encodedSign = $this->base64UrlEncode($sign);
        // 拼接上传凭证
        return $this->accessKey . ':' . $encodedSign . ':' . $encodedPolicy;
    }
    /**
     * Base64 URL安全编码
     */
    private function base64UrlEncode($data)
    {
        return str_replace(['+', '/'], ['-', '_'], base64_encode($data));
    }
    /**
     * Base64 URL安全解码(用于调试)
     */
    public function base64UrlDecode($data)
    {
        $base64 = str_replace(['-', '_'], ['+', '/'], $data);
        return base64_decode($base64);
    }
}
// 使用示例
$qiniu = new QiniuTokenManager(
    'YOUR_ACCESS_KEY',
    'YOUR_SECRET_KEY',
    'YOUR_BUCKET_NAME'
);
// 1. 简单上传
$simpleToken = $qiniu->simpleUploadToken('images/avatar.jpg', 3600);
// 2. 覆盖上传
$overwriteToken = $qiniu->overwriteUploadToken('files/document.pdf', 7200);
// 3. 限制MIME类型
$imageToken = $qiniu->mimeLimitToken('image/*', 'images/', 3600);
// 4. 回调上传
$callbackToken = $qiniu->callbackToken(
    'https://your-domain.com/callback.php',
    'key=$(key)&hash=$(etag)&fsize=$(fsize)',
    null,
    3600
);
// 5. 持久化处理
$persistentToken = $qiniu->persistentToken(
    'avthumb/mp4/ab/160k',
    'https://your-domain.com/notify.php',
    'videos/video.mp4',
    3600
);
?>

使用官方SDK(推荐)

<?php
// 首先通过 Composer 安装七牛云官方 SDK
// composer require qiniu/php-sdk
require 'vendor/autoload.php';
use Qiniu\Auth;
use Qiniu\Storage\UploadManager;
class QiniuUpload
{
    private $auth;
    private $bucket;
    public function __construct($accessKey, $secretKey, $bucket)
    {
        $this->auth = new Auth($accessKey, $secretKey);
        $this->bucket = $bucket;
    }
    /**
     * 生成简单上传凭证
     */
    public function getSimpleToken()
    {
        // 生成上传Token
        $token = $this->auth->uploadToken($this->bucket);
        return $token;
    }
    /**
     * 生成指定文件名上传凭证
     */
    public function getTokenWithKey($key)
    {
        $token = $this->auth->uploadToken($this->bucket, $key);
        return $token;
    }
    /**
     * 生成带策略的上传凭证
     */
    public function getTokenWithPolicy($policy)
    {
        // 具体的策略参数可以看官方文档
        $token = $this->auth->uploadToken($this->bucket, null, 3600, $policy);
        return $token;
    }
    /**
     * 生成带回调的上传凭证
     */
    public function getCallbackToken($callbackUrl)
    {
        $policy = [
            'callbackUrl' => $callbackUrl,
            'callbackBody' => 'key=$(key)&hash=$(etag)&fsize=$(fsize)',
            'callbackBodyType' => 'application/x-www-form-urlencoded'
        ];
        $token = $this->auth->uploadToken($this->bucket, null, 3600, $policy);
        return $token;
    }
    /**
     * 生成覆盖上传凭证
     */
    public function getOverwriteToken($key)
    {
        $policy = [
            'insertOnly' => 0 // 0表示允许覆盖
        ];
        $token = $this->auth->uploadToken($this->bucket, $key, 3600, $policy);
        return $token;
    }
}
// 使用示例
$uploader = new QiniuUpload(
    'YOUR_ACCESS_KEY',
    'YOUR_SECRET_KEY',
    'YOUR_BUCKET_NAME'
);
// 生成简单上传凭证
$token = $uploader->getSimpleToken();
// 返回给前端使用
header('Content-Type: application/json');
echo json_encode(['uptoken' => $token]);
?>

前端集成示例

<!-- 前端使用上传凭证 -->
<!DOCTYPE html>
<html>
<head>七牛上传示例</title>
</head>
<body>
    <input type="file" id="fileInput">
    <button onclick="uploadFile()">上传</button>
    <script src="https://unpkg.com/qiniu-js@3.x/dist/qiniu.min.js"></script>
    <script>
        // 从后端获取上传凭证
        async function getUploadToken() {
            const response = await fetch('/api/get-upload-token');
            const data = await response.json();
            return data.uptoken;
        }
        async function uploadFile() {
            const fileInput = document.getElementById('fileInput');
            const file = fileInput.files[0];
            if (!file) {
                alert('请选择文件');
                return;
            }
            // 获取上传凭证
            const token = await getUploadToken();
            // 配置上传
            const config = {
                useCdnDomain: true, // 使用CDN加速
                region: null // 自动选择上传区域
            };
            // 上传文件
            const putExtra = {
                fname: file.name,
                params: {},
                mimeType: null
            };
            // 创建上传实例
            const observable = qiniu.upload(
                file,           // 文件
                null,           // key,不指定则使用七牛生成的key
                token,          // 上传凭证
                config,         // 配置
                putExtra        // 额外参数
            );
            // 订阅上传进度
            const subscription = observable.subscribe({
                next: (res) => {
                    // 上传进度
                    const percent = Math.floor(res.total.percent);
                    console.log(`上传进度: ${percent}%`);
                    // 更新进度条
                    document.getElementById('progress').style.width = percent + '%';
                },
                error: (err) => {
                    console.error('上传失败:', err);
                    alert('上传失败');
                },
                complete: (res) => {
                    console.log('上传成功:', res);
                    alert('上传成功!');
                    // 拼接访问URL
                    const domain = 'YOUR_CDN_DOMAIN'; // 你的CDN域名
                    const url = `http://${domain}/${res.key}`;
                    console.log('文件地址:', url);
                }
            });
        }
    </script>
</body>
</html>

这个方案提供了不同复杂度的实现,从基础的手动生成到使用官方SDK,以及前端集成示例,生产环境建议使用官方SDK以确保安全性和稳定性。

抱歉,评论功能暂时关闭!