对象存储

  • PHP SDK

    最近更新时间:2017-10-26 11:42:25

    此 SDK ( version: 7.x.x ) 适用于PHP >= 5.3.0

    此 SDK 包含了如下几个功能:

    • 数据的上传和下载。

    • 数据的管理: 复制,移动,删除,获取元信息,列取文件等功能。

    • 数据的处理: 图片的处理,音视频的处理,文档的处理等功能。

    • CDN 相关功能: 文件刷新,预取,日志下载等功能。

    SDK(version: 6.x.x 适用于PHP >= 5.1.0): PHP SDK历史文档

    安装

    支持以下3种安装 SDK 的方法,推荐通过Composer安装 SDK。

    • 使用 Composer 安装

    Composer是 PHP 依赖管理工具。你可以在自己的项目中声明所依赖的外部工具库,Composer 会自动帮你安装这些依赖的库文件。

       1. 安装 Composer

        curl -sS https://getcomposer.org/installer | php
    

       2. 运行 Composer 命令安装最新稳定版本的 SDK:

        php composer.phar require qiniu/php-sdk
    

       3. Require Composer 生成的 autoloader:

        <?php
         require 'vendor/autoload.php';
    

    如果需要更详细的关于 Composer 的使用说明,你可以访问Composer官方网站,或对应的中文网站

    • 直接下载 Composer 安装包

      鉴于某些原因,国内的用户使用 Composer 下载依赖库比较慢,开发者也可以直接下载我们准备好的符合 Composer 规范的vendor 压缩包并在本地解压。解压后的内容和使用 Composer 方式获取到的内容完全一致,之后的使用方式也一致。

    • 下载源代码包

      直接下载源代码压缩包并解压是另一种 SDK 的安装方法。不过因为有版本更新的维护问题,这种安装方法并不推荐,仅作为万一 Composer 安装有问题的情况下的一种备选。并且,源码中也包含 SDK 的 autoloader

      下载源代码包后,解压到您的项目中。 然后在您的项目中引入 autoloader:

        require 'path_to_sdk/autoload.php';
      

    基本使用方法

    安装好 SDK 后,接下来介绍如何使用 SDK。在使用 SDK 之前,需要注册一个七牛帐号,并登录控制台获取一对有效的AccessKey和SecretKey,并且详细阅读[安全机制][securityHref]以进一步了解如何正确使用和管理密钥。

    引入SDK

    无论你是通过哪种方式安装的 SDK,只需要一句简单的 require 语句将安装好的SDK包含到你的项目中。请参考如下表格,找到适合你的安装方式,将SDK引入到你的项目中。请用你项目中的实际路径替换 path_to_sdk

    安装方式 引入SDK
    Composer 安装 require 'path_to_sdk/vendor/autoload.php';
    下载Composer安装包 require 'path_to_sdk/vendor/autoload.php';
    下载源码安装包 require 'path_to_sdk/autoload.php';

    SDK结构

    可以直接查看我们的SDK目录,即可大致了解我们 SDK 的结构。

    • 最外层包含:配置文件, 鉴权和一些公共的函数。
    • HTTP 目录主要包含了一些对 http 进行封装的类,这块你可以不用关心。
    • Storage 目录主要包含两大块:Bucket 中文件的管理和文件的上传。
    • Processing 目录主要包含文件的处理,文件处理又包含两个方面:同步处理和异步处理。
    • Cdn 目录主要包含了 CDN 的相关 API ,有文件的刷新和预取,CDN 日志的下载等方法。

    为了帮助您更好的了解和使用我们的sdk,我们还提供了各种使用示例。 如果使用中遇到问题,可以通过Github或者我们的工单进行反馈。下面我们对一些关键点进行简单的介绍,方便您快速入门。

    鉴权类

    在使用七牛的SDK的过程中鉴权是很重要的一块,不管是上传鉴权,下载签权, 还是回调的签权。 PHP SDK 中的 Auth 类封装了所有的鉴权方式。 所以在使用 PHP SDK 时基本都会先对鉴权类进行初始化:

    <?php
    require 'path_to_sdk/vendor/autoload.php';
    use Qiniu\Auth;
      // 用于签名的公钥和私钥
    $accessKey = 'Access_Key';
    $secretKey = 'Secret_Key';
    
      // 初始化签权对象
    $auth = new Auth($accessKey, $secretKey);
    

    初始化好Auth 类后,就可以调用相应的方法了,比如生成私有下载链接方法 privateDownloadUrl,获取上传Token方法 uploadToken,验证回调方法 verifyCallback等。

    上传类

    在上传类 UploadManager 中主要负责文件的上传, 七牛的文件上传分为两种上传方式:表单上传分片上传。当然在PHP SDK中你不用关心这个细节,只需要调用 UploadManager 中的上传方法即可。UploadManager 中的上传方法会根据上传文件的大小选择不同的上传方式,小于4MB的进行表单上传,大于4MB的进行分片上传。 以下一个简单的示例使你更清晰地了解如何初始上传对象:

    require 'path_to_sdk/vendor/autoload.php';
    use Qiniu\Auth;
    use Qiniu\Storage\UploadManager;
    $accessKey = 'Access_Key';
    $secretKey = 'Secret_Key';
    $auth = new Auth($accessKey, $secretKey);
    
    $bucket = 'Bucket_Name';
    
    // 生成上传Token
    $token = $auth->uploadToken($bucket);
    
    // 构建 UploadManager 对象
    $uploadMgr = new UploadManager();
    

    空间名请参阅空间

    资源管理类

    在资源管理类 BucketManager 中主要负责空间中文件的管理: 复制,移动,删除,获取元信息,修改Mime,拉取文件到七牛空间,列取文件。 以下一个简单的示例使你更清晰地了解如何初始空间管理对象:

    require 'path_to_sdk/vendor/autoload.php';
    use Qiniu\Auth;
    use Qiniu\Storage\BucketManager;
    $accessKey = 'Access_Key';
    $secretKey = 'Secret_Key';
      //初始化Auth状态
    $auth = new Auth($accessKey, $secretKey);
      //初始化BucketManager
    $bucketMgr = new BucketManager($auth);
    

    触发持久化类

    触发持久化类 PersistentFop 中主要负责对空间中已上传的文件进行异步处理,并对异步处理的结果进行持久化操作。比如对已上传的视频文件进行转码,拼接,切片,水印等处理,并将处理后的结果保存在空间中。

    require 'path_to_sdk/vendor/autoload.php';
    use Qiniu\Auth;
    use Qiniu\Processing\PersistentFop;
    $accessKey = 'Access_Key';
    $secretKey = 'Secret_Key';
    $auth = new Auth($accessKey, $secretKey);
      // 要转码的文件所在的空间
    $bucket = 'Bucket_Name';
      // 转码时使用的队列名称 
    $pipeline = 'abc';
      // 初始化
    $pfop = new PersistentFop($auth, $bucket, $pipeline);
    

    场景化示例

    接下来我们,对一些常见的使用场景,提供一些简单的Demo,使您更快速的接入七牛。

    Hello, World!

    在了解了基本概念和编程模型后,我们现在以最短的篇幅将第一个云存储服务的示例程序跑起来。该示例的目标是:将一个本地小文件上传到指定的存储空间中。

    提交页面

    我们先写一个简单的 HTML 表单来供用户上传到七牛存储空间信息并选择一个本地文件。在点击提交按钮后,浏览器会发送一个 HTTP 请求到七牛上传域名执行文件上传动作。

    <form method="post" action="http://up.qiniu.com" enctype="multipart/form-data">
      <input name="token" type="hidden" value="<upload_token>">
      <input name="file" type="file" />
      <input type="submit" value="上传"/>
    </form>
    

    上传动作

    也许你注意到了这个上传表单有一个token字段,所以想要使用 form 直传七牛一个文件,必须在页面加载的时候,向服务端请求token并设置到这个表单项中。服务端生成这个token涉及到我们 SDK 中提供的方法:Qiniu\Auth

    关键代码如下所示:

    use Qiniu\Auth;
    $bucket = '<your_bucket>';
    $accessKey = '<your_access_key>';
    $secretKey = '<your_secret_key>';
    $auth = new Auth($accessKey, $secretKey);
    $upToken = $auth->uploadToken($bucket);
    echo $upToken;
    

    可以看出,以上代码主要做了以下几步工作:

    1. 使用你的 AccessKey 及 SecretKey 用于初始化Auth对象
    2. 调用初始化的对象Auth对象的方法uploadToken来生成上传token

    到这里为止,第一个示例就可以运行起来了。您可以查看该示例的在线演示。您也可以直接获取和查看该示例的源代码

    小结

    这个示例仅用于演示如何使用 PHP SDK 快速运行第一个云存储服务的程序。本事例尽可能简单的展现七牛的表单上传,因此请大家仅将本示例作为学习 PHP SDK 的一个步骤,而不是在产品环境中应用。

    一个完整的移动应用

    我们将详细介绍如何使用 PHP SDK 与其他端配合构建一个类似于微信朋友圈的移动应用。

    在这个移动应用里终端用户可以进行如下操作:

    1. 使用预设的帐号密码登录(不支持注册新帐号)
    2. 查看自己和朋友分享的照片以及描述(不支持评论)
    3. 上传一张新图片,并添加一段描述。

    Demo截图

    总体架构

    对于此类应用,我们推荐的总体架构如下图所示:

    arch-with-callback

    对于此架构有以下关键要点:

    1. AK/SK 只能在业务服务器端使用,如果将 AK 和 SK 同时保存或者传输到移动端会有严重的信息泄露风险。
    2. AK/SK 是企业帐号信息,业务服务器需要有自己的帐号数据库,对应到每一个终端用户的帐号信息。
    3. 由于不同的业务都需要存放一些跟文件相关的描述信息,且图片又属于不同的终端用户,因此需要维护文件管理表,以管理文件的描述信息和所有者关系。

    基于以上这些关键要点,我们来设计和实现我们的 PHP 版本的业务服务器。

    接口设计

    我们来简单的设计我们的业务服务器接口。

    帐号验证:

    POST /login.php HTTP/1.1
    HOST: demos.qiniu.io
    Accept: */*
    Content-Type: application/x-www-form-urlencoded
    
    
    uname=<username>&pwd=<password>
    

    获取文件列表:

    POST /files.php HTTP/1.1
    HOST: demos.qiniu.io
    Accept: */*
    Cookie: <cookie>
    Content-Type: application/x-www-form-urlencoded
    

    获取上传授权,因为移动端并不知道 AK/SK 信息,客户端在需要上传文件时都需要向业务服务器发起一个获取上传授权的请求:

    POST /uptoken.php HTTP/1.1
    HOST: demos.qiniu.io
    Accept: */*
    Cookie: <cookie>
    Content-Type: application/x-www-form-urlencoded
    

    回调,移动端会直接上传文件到云存储服务,因此业务服务器不需要提供上传接口,但是需要提供一个供云存储服务在接收到文件后的回调接口。回调接口的响应内容会由云存储服务返回给移动端:

    POST /callback.php HTTP/1.1
    HOST: demos.qiniu.io
    Accept: */*
    Cookie: <cookie>
    Content-Type: application/x-www-form-urlencoded
    
    uid=<uid>&fname=<file_name>&fkey=<file_key>&desc=<description>
    

    数据表,业务服务需要一个业务数据库的支撑以管理提到的帐号信息和文件信息。在本示例中我们选用 MySQL 来搭建业务数据库。帐号表:

    字段名 字段类型 字段说明
    id int 唯一标识。
    uid int 唯一用户标识。
    uname char(128) 用户名,格式为邮箱如 admin@example.com 。
    password char(128) 加密后的密码。
    status int 1: active
    0: disabled

    文件信息表:

    字段名 字段类型 字段说明
    id int 唯一标识。
    uid int 用户唯一标识。
    fname char(512) 文件的显示名
    key char(512) 文件对应到云存储服务中的唯一标识。
    createTime time 上传时间。
    description char(2048) 文件的描述内容。

    相应的 SQL 语句如下:

    create database qspace;
    
    CREATE TABLE users (
          uid            INT NOT NULL AUTO_INCREMENT,
          uname          VARCHAR(128) NOT NULL,
          password       VARCHAR(128) NOT NULL,
          status         INT, 
          PRIMARY KEY (uid)
    );
    
    CREATE TABLE files_info (
          id             INT NOT NULL AUTO_INCREMENT,
          uid            INT NOT NULL,
          fname          VARCHAR(512) NOT NULL,
          fkey           VARCHAR(512) NOT NULL,
          createTime     INT, 
          description    VARCHAR(1024), 
          PRIMARY KEY (id),
          FOREIGN KEY (uid) REFERENCES users(uid),
          UNIQUE INDEX (id)
    );
    

    服务实现

    接下来我们一步步的实现以上定义的接口。这些实现主要考虑流程的完整性,因此在安全性上没有做充分的考量,请不要直接使用于产品环境中。

    配置文件

    我们需要在一个地方存放全局的设置。本示例中我们直接用一个 config.php 文件包含若干全局变量的方式来解决这个问题。

    <?php
        class Config
        {
            const DB_NAME = 'qspace',
                  DB_USER = 'root',
                  DB_PWD = '****',
                  DB_HOST = '<your_db_host>',
                  ACCESS_KEY = '<your_access_key>',
                  SECRET_KEY = '<your_secret_key>',
                  BUCKET_NAME = '<your_bucket_name>';
        }
    

    帐号验证

    帐号验证的逻辑非常简单,就是将请求中包含的用户信息与数据库表中的信息进行比对,因此不需要涉及 SDK 的功能。

    require_once 'db.php';
    session_start();
        if(!isset($_POST['uname']) && !isset($_POST['pwd']))
    {
        http_response_code(401);
        $resp = array('status' => 'failed', 'msg' => 'please input username & password!');
          echo json_encode($resp);
          return;
     }
    
    $uname = $_POST['uname'];
    $_pwd = $_POST['pwd'];
    
    $salt = 'Qiniu' . $uname;
    $pwd = crypt($_pwd, $salt);
    
    $stmt = $DB->prepare('select * from users where uname = :name');
    $stmt->execute(array('name' => $uname));
    $user = $stmt->fetch();
        if ($user['password'] !== $pwd)
        {
          http_response_code(401);
          $resp = array('status' => 'failed', 'msg' => 'incorrect username or password!');
          echo json_encode($resp);
          return;
        }
    
    $_SESSION['uid'] = $user['uid'];
    $_SESSION['uname'] = $uname;
    
    $resp = array('status' => 'ok', 'uname' => $uname);
    echo json_encode($resp);
    

    获取文件列表

    同帐号验证功能一样,获取文件列表也只是查询数据库,因此不多做解释。

    <?php
    require_once 'db.php';
    session_start();
    $uid = $_SESSION['uid'];
        if(!isset($uid))
        {
            header('location: login.php');
            return;
        }
    $stmt = $DB->prepare('select * from files_info where uid = :uid');
    $stmt->execute(array('uid' => $uid));
    $files = $stmt->fetchAll();
    
    echo json_encode($files);
    

    获取上传授权

    客户端在需要上传文件时都需要先向业务服务器发起一个获取上传授权的请求。 SDK 中的 Qiniu\Auth 类提供了 uploadToken($bucket, ...) 方法,可以非常便利的生成对应的上传授权。

    require_once 'vendor/autoload.php';
    require_once 'db.php';
    require_once 'config.php';
    use Qiniu\Auth;
    session_start();
    $uid = $_SESSION['uid'];
    if(!isset($uid))
        {
          header('location: login.php');
          return;
        }
    $bucket = Config::BUCKET_NAME;
    $accessKey = Config::ACCESS_KEY;
    $secretKey = Config::SECRET_KEY;
    $auth = new Auth($accessKey, $secretKey);
    
    $policy = array(
          'callbackUrl' => 'http://172.30.251.210/callback.php',
          'callbackBody' => '{"fname":"$(fname)", "fkey":"$(key)", "desc":"$(x:desc)", "uid":' . $uid . '}'
          );
    
     $upToken = $auth->uploadToken($bucket, null, 3600, $policy);
    
     header('Access-Control-Allow-Origin:*');
        echo $upToken;
    

    回调

    在收到回调时,通常表示一个文件已经成功上传。回调会包含该文件所对应的描述信息。因此业务服务器在收到回调后,需要将相应的文件信息写入到文件信息表中。

    <?php
    require_once 'db.php';
    require_once 'vendor/autoload.php';
    $_body = file_get_contents('php://input');
    $body = json_decode($_body, true);
    $uid = $body['uid'];
    $fname = $body['fname'];
    $fkey = $body['fkey'];
    $desc = $body['desc'];
    
    $date = new DateTime();
    $ctime = $date->getTimestamp();
    
    $stmt = $DB->prepare('INSERT INTO files_info (uid, fname, fkey, createTime, description) VALUES (:uid, :fname, :fkey, :ctime, :desc);');
     $ok = $stmt->execute(array('uid' => $uid, 'fname' => $fname, 'fkey' => $fkey, 'ctime' => $ctime, 'desc' => $desc));
    
    header('Content-Type: application/json');
        if (!$ok)
        {
          $resp = $DB->errorInfo();
          http_response_code(500);
          echo json_encode($resp);
          return;
        }
     $resp = array('ret' => 'success');
        echo json_encode($resp);
    

    服务监控

    为了确认服务的正常运行,我们还实现了一个简单的监控页面以查看所有上传的图片。该页面假设admin的管理员才有权访问。后端代码就是将用户上传的文件从数据库中列取出来。

    
    require_once 'vendor/autoload.php';
    require_once 'db.php';
    
    if (!$_SESSION['logged'])
        {
          header('login.php');
        }
    
    $id = $_POST['id'];
    if ($id)
        {
          $stmt = $DB->prepare('delete from files_info where id = :id');
          $stmt->execute(array('id' => $id));
        }
    $stmt = $DB->prepare('select * from files_info');
    $stmt->execute();
    $files = $stmt->fetchAll();
    $smarty = new Smarty();
    $smarty->assign('files', $files);
    $smarty->display('file_mgr.tpl');
    

    前端页面使用 Bootstrap 的控件实现,并使用 Smarty 模板技术来循环生成最终页面:

      {foreach from=$files item=file}
      <tr>
          <td><a href="{$file[uid]}">{$file["uid"]}</a></td>
          <td>{$file["fname"]}</td>
          <td>{$file["fkey"]}</td>
          <td>{$file["description"]}</td>
          <td>{$file["createTime"]}</td>
          <td><a class="del" href="" data-fid="{$file['id']}">删除</a></td>
      </tr>
      {/foreach}
    

    移动端实现

    本示例包含一个 Android 客户端的实现。因为本文档的重心是结合例子讲解 PHP SDK 的使用,因此这里就不详细讲解如何实现 Android 客户端了。您可以下载和安装移动客户端的安装包,或查看移动客户端的源代码

    小结

    您可以在 Android 手机或者模拟器上安装和运行本示例的移动端应用,上传一张图片,并查看图片列表和描述。这个示例的重点在于讲解一个推荐的产品架构,以及各个子系统如何协同工作。

    接下来我们再围绕几个示例遍历七牛云提供的其他强大功能。接下来的示例都不会再像这个示例一样提供一个完整的移动互联网产品架构,而是把重点放在功能介绍上。您可以举一反三,快速的在本章介绍的示例上进行修改和加强,就可以快速开发出各种有趣的移动互联网应用。移动端安装包,或查看移动客户端的源代码admin管理界面

    图片处理

    我们将围绕一个功能相对完备的示例来讲解图片处理的主要用法,并顺便介绍 PHP SDK 的资源管理功能。

    这个示例用户可以上传图片,选择图片处理模式,输入相应的处理参数,然后可以查看处理的结果。用户还可以点选不同的图片以显示图片的鉴黄信息和鉴别广告的信息, 以及获取图片的基本信息,平均色,exif信息等。

    下面我们分步来实现这个示例。前端实现使用了Bootstrap和我们的js-sdk,后端使用 phpsdk 生成上传的 token 。

    生成上传token

    首先安装我们的 phpsdk,然后引入相应文件并调用接口生成上传token:

    require_once 'vendor/autoload.php';
    require_once 'config.php';
    use Qiniu\Auth;
    $bucket = Config::BUCKET_NAME;
    $accessKey = Config::ACCESS_KEY;
    $secretKey = Config::SECRET_KEY;
    $auth = new Auth($accessKey, $secretKey);
    $upToken = $auth->uploadToken($bucket);
    $ret = array('uptoken' => $upToken);
    echo json_encode($ret);
    

    上传部分相关的 html 代码:

    <div id="container">
         <button id="pickfiles" class="btn btn-primary btn-lg btn-block" type="submit">上传图片</button>
    </div>
    

    上传对应的调用 jssdk 相关代码:

        var uploader = Qiniu.uploader({
            runtimes: 'html5,flash,html4', //上传模式,依次退化
            browse_button: 'pickfiles', //上传选择的点选按钮,**必需**
            uptoken_url: 'uptoken.php', //Ajax请求upToken的Url,**强烈建议设置**(服务端提供)
            domain: 'http://rwxf.qiniudn.com/', //bucket 域名,下载资源时用到,**必需**
            container: 'container', //上传区域DOM ID,默认是browser_button的父元素,
            max_file_size: '100mb', //最大文件体积限制
            flash_swf_url: 'plupload/Moxie.swf', //引入flash,相对路径
            max_retries: 3, //上传失败最大重试次数
            dragdrop: true, //开启可拖曳上传
            drop_element: 'container', //拖曳上传区域元素的ID,拖曳文件或文件夹后可触发上传
            chunk_size: '4mb', //分块上传时,每片的体积
            auto_start: true, //选择文件后自动上传,若关闭需要自己绑定事件触发上传
            init: {
                'UploadProgress': function(up, file) {
                    $('#pickfiles').prop('disabled', true).html('图片上传中...');
                },
                'FileUploaded': function(up, file, info) {
    
                    $('#pickfiles').prop('disabled', false).html('上传图片');
                    var res = JSON.parse(info);
                    imgUrl = up.getOption('domain') + res.key;
                    refresh(imgUrl);
                },
                'Error': function(up, err, errTip) {
                    $('#pickfiles').prop('disabled', false).html('上传图片');
                }
            }
        });
    

    图片处理

    图片处理的过程非常简单,就是将我们的图片处理 fop 以及对应的参数拼接在图片地址后面即可。基本不需要用到 SDK 的功能,当然你也可以使用我们的 jssdk 进行图片地址和处理参数的拼接。 比如一个图片:http://qiniuphotos.qiniudn.com/gogopher.jpg,现在我们对这个图片进行200x200的等比缩放,然后再进行居中剪裁,可以使用imageView2的模式1,最终得到的图片:http://qiniuphotos.qiniudn.com/gogopher.jpg?imageView2/1/w/200/h/200

    更多处理规格请参考图片基本处理 (imageView2)文档。

    图片信息

    {
      format: "jpeg",
      width: 640,
      height: 427,
      colorModel: "ycbcr",
      orientation: "Top-left"
    }
    
    {
      RGB: "0x85694d"
    }
    
    {
        ApertureValue: {
            val: "5.00 EV (f/5.7)",
            type: 5
        },
        ColorSpace: {
            val: "sRGB",
            type: 3
        },
        ComponentsConfiguration: {
            val: "- - - -",
            type: 7
        },
        ...
    }
    

    自定义数据处理功能

    除了我们官方提供的强大图片处理功能外,我们的自定义数据处理平台还提供了强大的第三方数据处理服务。在本例中我们就来尝试一下图片鉴黄服务(nrop)

    要使用 NROP 功能,用户需要先在管理平台上的第三方数据处理开启本功能。开启后使用方式与一般的数据处理指令完全一致(比如获取 EXIF 信息的接口),仅需要使用带 nrop 参数的 GET 请求即可,返回的 HTTP 响应内容为一个包含鉴定结果的 JSON 字符串。示例代码如下:

    http://qiniuphotos.qiniudn.com/gogopher.jpg?nrop

    {
        statistic: [
            0,
            0,
            1
        ],
        reviewCount: 0,
        fileList: [{
            rate: 0.9946920275688171,        // 介于0-1间的浮点数,表示该图像被识别为某个分类的概率值,概率越高、机器越肯定
            label: 2,                        // 0:色情; 1:性感; 2:正常
            name: "739a77baf4ff2d5eae5fe56602fc0cbe/gogopher.jpg",
            review: false                    //是否需要人工复审该图片,鉴黄服务是否对结果确定(true:不确定,false:确定)
        }],
        nonce: "0.5508577267173678",
        timestamp: 1437903830,
        code: 0,
        message: "success"
    }
    

    我们提供的完整示例已经包含了对 NROP 的调用,以及对广告的鉴定,您可以体验一下效果。

    小结

    这个示例结束后,相信你已经比较了解我们的平台是如何支持图片内容的编辑,基本上这些动作都只是一个简单的 GET 请求即可完成,甚至都不需要依赖于 SDK。您可以查看本示例的在线演示,或查看和下载本示例的完整源代码

    音视频处理

    用一个示例详细讲解七牛云对音视频和流媒体格式的强大支持。该示例的目标为完成以下动作:

    1. 支持断点续传的大文件上传,因为视频文件通常比较大,难以用单次 POST 请求完成上传;
    2. 支持上传后异步执行的自动转码动作,生成若干不同规格的目标视频,分别适合在手机和电脑上播放;
    3. 将文件转换为 HLS 格式存放,以支持边下载边播放的效果;
    4. 为视频打上一个图片水印;
    5. 统一从每一个视频文件抽取一个固定时间点的画面作为预览图片;
    6. 在网页播放器中播放生成的视频文件;

    我们选用 plupload 作为我们的上传控件,并使用 videojs 作为我们的网页播放器。其他采用的技术与之前的示例一致,主要是 Bootstrap 和 Smarty 。因为文件为客户端直传,因此我们也需要提供一个回调服务,以便于接收上传和转码这些异步任务的完成事件。为了简单起见,该示例就不再实现一个独立的业务数据库了,直接从目标存储空间获取文件信息。

    大文件上传

    因为大文件上传必须在浏览器端进行,因此我们就不演示如何用 PHP SDK 做断点续上传了。网页端的大文件上传我们可以用定制版本的 plupload 来支持。 具体可以查看我们的jssdk

    上传后自动转码

    我们可以通过设置上传策略来通知云存储服务在上传完成后自动发起一个异步的任务。上传策略在调用上传接口时作为参数传入。 这里的转码过程需要支持转为 HLS 格式,并且在转码后打上视频水印。具体生成上传策略的代码为:

     $bucket = Config::BUCKET_NAME;
     $auth = new Auth(Config::AK, Config::SK);
    
     $wmImg = Qiniu\base64_urlSafeEncode('http://rwxf.qiniudn.com/logo-s.png');
     $pfopOps = "avthumb/m3u8/noDomain/1/wmImage/$wmImg";
     $policy = array(
            'persistentOps' => $pfopOps,
            'persistentNotifyUrl' => 'http://<your_notify_url>',
        );
    
     $upToken = $auth->uploadToken($bucket, null, 3600, $policy);
        echo json_encode(array('uptoken' => $upToken));
    

    抽取视频截图

    我们可以从上传视频中截取固定时间点的帧,以作为这些视频的封面图片。视频截图如下所示:

    http://<your_uploaded_video>?vframe/jpg/offset/5
    

    视频浏览与播放

    在完成以上工作后,接下来的工作就简单了。我们可以生成一个列表网页,每个列表项都是一张视频截图,点击视频截图会弹出一个播放面板。因为类似的前端代码已经在本文档展示过,这里就不再多展示一次。

    小结

    视频的示例就到这里完成了。您可以直接查看本示例的在线演示,或下载和查看本示例的完整源代码

    需要注意的是,我们这边使用了videojs的开源播放器, 世面上还有其他比较优秀的播放器,具体你可以参考播放器推荐

    另外,对于视频内容,CDN 的选择会是一个影响视频播放是否能够足够流畅的关键因素。在融合 CDN 管理平台会给列出的可用 CDN 线路标注是否适用于视频加速,请合理选择。


    下面将展示 PHP-SDK 中具体功能和演示代码

    文件上传

    上传流程

    在七牛云存储中,整个上传流程大致分为以下几步:

    1. 业务服务器颁发上传凭证给客户端(终端用户)
    2. 客户端凭借上传凭证上传文件到七牛
    3. 在七牛获得完整数据后,发起一个 HTTP 请求回调到业务服务器
    4. 业务服务器保存相关信息,并返回一些信息给七牛
    5. 七牛原封不动地将这些信息转发给客户端(终端用户)

    注意:回调到业务服务器的过程是可选的,它取决于业务服务器颁发的上传凭证。如果没有回调,七牛会返回一些标准的信息(例如文件的 hash)给客户端。 如果上传发生在业务服务器,以上流程简化为:

    1. 业务服务器生成上传凭证
    2. 凭借上传凭证上传文件到七牛
    3. 后续工作,例如保存一些相关信息

    上传凭证

    上传凭证实际上是用 AccessKey/SecretKey 进行数字签名的上传策略 Qiniu_RS_PutPolicy,它控制着整个上传流程的行为。具体上传策略参数的解释可见 上传凭证

     private static $policyFields = array(
            'callbackUrl',
            'callbackBody',
            'callbackHost',
            'callbackBodyType',
    
            'returnUrl',
            'returnBody',
    
            'endUser',
            'saveKey',
            'insertOnly',
    
            'detectMime',
            'mimeLimit',
            'fsizeMin',
            'fsizeLimit',
    
            'persistentOps',
            'persistentNotifyUrl',
            'persistentPipeline',
    
            'deleteAfterDays',
            'fileType',
            'isPrefixalScope',
        );
    

    在构建上传凭证之前,我们首先要定义鉴权对象Auth

    use \Qiniu\Auth;
    
    $accessKey = "QINIU_ACCESS_KEY"
    $secretKey = "QINIU_SECRET_KEY"
    $bucket = "your bucket name"
    
    // 初始化Auth状态
    $auth = new Auth($accessKey, $secretKey);
    

    简单上传的凭证

    最简单的上传凭证只需要 AccessKeySecretKeyBucket 就可以。

    $expires = 3600;
    $policy = null;
    $upToken = $auth->uploadToken($bucket, null, $expires, $policy, true);
    print($upToken . "\n");
    

    默认情况下,在不指定上传凭证的有效时间情况下,默认有效期为1个小时。也可以自行指定上传凭证的有效期,例如:

    //自定义凭证有效期(示例2小时,expires单位为秒,为上传凭证的有效时间)
    $expires = 7200;
    $upToken = $auth->uploadToken($bucket, null, $expires, $policy, true);
    print($upToken . "\n");
    

    覆盖上传的凭证

    覆盖上传除了需要简单上传所需要的信息之外,还需要想进行覆盖的文件名称,这个文件名称同时可是客户端上传代码中指定的文件名,两者必须一致。

     //覆盖上传
    $expires = 3600;
    $keyToOverwrite = 'qiniu.mp4';
    $upToken = $auth->uploadToken($bucket, $keyToOverwrite, $expires, $policy, true);
    print($upToken . "\n");
    

    自定义上传回复的凭证

    $returnBody = '{"key":"$(key)","hash":"$(etag)","fsize":$(fsize),"bucket":"$(bucket)","name":"$(x:name)"}';
    $policy = array(
        'returnBody' => $returnBody
    );
    $upToken = $auth->uploadToken($bucket, null, $expires, $policy, true);
    print($upToken . "\n");
    

    默认情况下,文件上传到七牛之后,在没有设置returnBody或者回调相关的参数情况下,七牛返回给上传端的回复格式为hashkey,例如:

    {"hash":"Ftgm-CkWePC9fzMBTRNmPMhGBcSV","key":"qiniu.jpg"}
    

    有时候我们希望能自定义这个返回的JSON格式的内容,可以通过设置returnBody参数来实现,在returnBody中,我们可以使用七牛支持的魔法变量自定义变量

    //自定义返回值
    $returnBody = '{"key":"$(key)","hash":"$(etag)","fsize":$(fsize),"name":"$(x:name)"}';
    $policy = array(
        'returnBody' => $returnBody
    );
    $upToken = $auth->uploadToken($bucket, null, $expires, $policy, true);
    print($upToken . "\n");
    

    则文件上传到七牛之后,收到的回复内容如下:

    {"key":"qiniu.jpg","hash":"Ftgm-CkWePC9fzMBTRNmPMhGBcSV","bucket":"if-bc","fsize":39335,"name":"qiniu"}
    

    带回调业务服务器的凭证

    上面生成的自定义上传回复的上传凭证适用于上传端(无论是客户端还是服务端)和七牛服务器之间进行直接交互的情况下。在客户端上传的场景之下,有时候客户端需要在文件上传到七牛之后,从业务服务器获取相关的信息,这个时候就要用到七牛的上传回调及相关回调参数的设置。

    $policy = array(
        'callbackUrl' => 'http://api.example.com/qiniu/upload/callback',
        'callbackBody' => '{"key":"$(key)","hash":"$(etag)","fsize":$(fsize),"bucket":"$(bucket)","name":"$(x:name)"}',
        'callbackBodyType' => 'application/json'
    );
    $upToken = $auth->uploadToken($bucket, null, $expires, $policy, true);
    print($upToken . "\n");
    

    在使用了上传回调的情况下,客户端收到的回复就是业务服务器响应七牛的JSON格式内容。 通常情况下,我们建议使用application/json格式来设置callbackBody,保持数据格式的统一性。实际情况下,callbackBody也支持application/x-www-form-urlencoded格式来组织内容,这个主要看业务服务器在接收到callbackBody的内容时如何解析。例如:

    $policy = array(
        'callbackUrl' => 'http://api.example.com/qiniu/upload/callback',
        'callbackBody' => 'key=$(key)&hash=$(etag)&bucket=$(bucket)&fsize=$(fsize)&name=$(x:name)'
    );
    $upToken = $auth->uploadToken($bucket, null, $expires, $policy, true);
    print($upToken . "\n");
    

    带数据处理的凭证

    七牛支持在文件上传到七牛之后,立即对其进行多种指令的数据处理,这个只需要在生成的上传凭证中指定相关的处理参数即可。

    //持久化数据处理的上传凭证
    $saveMp4Entry = \Qiniu\base64_urlSafeEncode($bucket . ":avthumb_test_target.mp4");
    $saveJpgEntry = \Qiniu\base64_urlSafeEncode($bucket . ":vframe_test_target.jpg");
    $avthumbMp4Fop = "avthumb/mp4|saveas/" . $saveMp4Entry;
    $vframeJpgFop = "vframe/jpg/offset/1|saveas/" . $saveJpgEntry;
    $policy = array(
        'persistentOps' => $avthumbMp4Fop . ";" . $vframeJpgFop,
        'persistentPipeline' => "video-pipe",
        'persistentNotifyUrl' => "http://api.example.com/qiniu/pfop/notify",
    );
    $upToken = $auth->uploadToken($bucket, null, $expires, $policy, true);
    print($upToken . "\n");
    

    队列 pipeline 请参阅创建私有队列;转码操作具体参数请参阅音视频转码;saveas 请参阅处理结果另存

    带自定义参数的凭证

    七牛支持客户端上传文件的时候定义一些自定义参数,这些参数可以在returnBodycallbackBody里面和七牛内置支持的魔法变量(即系统变量)通过相同的方式来引用。这些自定义的参数名称必须以x:开头。例如客户端上传的时候指定了自定义的参数x:namex:age分别是stringint类型。那么可以通过下面的方式引用:

      returnBody: '{"key":"$(key)","hash":"$(etag)","fsize":$(fsize),"bucket":"$(bucket)","name":"$(x:name)","age":$(x:age)}'
    

    或者

      callbackBody: '{"key":"$(key)","hash":"$(etag)","fsize":$(fsize),"bucket":"$(bucket)","name":"$(x:name)","age":$(x:age)}'
    

    综合上传凭证

    上面的生成上传凭证的方法,都是通过设置上传策略🔗相关的参数来支持的,这些参数可以通过不同的组合方式来满足不同的业务需求,可以灵活地组织你所需要的上传凭证。

    服务端直传

    服务端直传是指客户利用七牛服务端SDK从服务端直接上传文件到七牛云,交互的双方一般都在机房里面,所以服务端可以自己生成上传凭证,然后利用SDK中的上传逻辑进行上传,最后从七牛云获取上传的结果,这个过程中由于双方都是业务服务器,所以很少利用到上传回调的功能,而是直接自定义returnBody来获取自定义的回复内容。

    文件上传

    最简单的就是上传本地文件,直接指定文件的完整路径即可上传。 七牛php-sdk会判断文件大小,根据文件大小选择使用表单上传和分片上传。这里只需要调用 putFile 方法就可以了。

    // 引入鉴权类
    use Qiniu\Auth;
    
    // 引入上传类
    use Qiniu\Storage\UploadManager;
    
    // 需要填写你的 Access Key 和 Secret Key
    $accessKey ="your accessKey";
    $secretKey = "your secretKey"
    $bucket = "your bucket name";
    
    // 构建鉴权对象
    $auth = new Auth($accessKey, $secretKey);
    
    // 生成上传 Token
    $token = $auth->uploadToken($bucket);
    
    // 要上传文件的本地路径
    $filePath = './php-logo.png';
    
    // 上传到七牛后保存的文件名
    $key = 'my-php-logo.png';
    
    // 初始化 UploadManager 对象并进行文件的上传。
    $uploadMgr = new UploadManager();
    
    // 调用 UploadManager 的 putFile 方法进行文件的上传。
    list($ret, $err) = $uploadMgr->putFile($token, $key, $filePath);
    echo "\n====> putFile result: \n";
    if ($err !== null) {
        var_dump($err);
    } else {
        var_dump($ret);
    }
    

    字节组上传

    $accessKey = getenv('QINIU_ACCESS_KEY');
    $secretKey = getenv('QINIU_SECRET_KEY');
    $bucket = getenv('QINIU_TEST_BUCKET');
    
    $auth = new Auth($accessKey, $secretKey);
    $token = $auth->uploadToken($bucket);
    $uploadMgr = new UploadManager();
    
    //----------------------------------------upload demo1 ----------------------------------------
    // 上传字符串到七牛
    list($ret, $err) = $uploadMgr->put($token, null, 'content string');
    echo "\n====> put result: \n";
    if ($err !== null) {
        var_dump($err);
    } else {
        var_dump($ret);
    }
    

    解析自定义回复内容

    有些情况下,七牛返回给上传端的内容不是默认的hashkey形式,这种情况下,可能出现在自定义returnBody或者自定义了callbackBody的情况下,前者一般是服务端直传的场景,而后者则是接受上传回调的场景,这两种场景之下,都涉及到需要将自定义的回复进行内容解析,一般建议在交互过程中,都采用JSON的方式,这样处理起来方法比较一致。

    业务服务器验证七牛回调

    在上传策略里面设置了上传回调相关参数的时候,七牛在文件上传到服务器之后,会主动地向callbackUrl发送POST请求的回调,回调的内容为callbackBody模版所定义的内容,如果这个模版里面引用了魔法变量或者自定义变量,那么这些变量会被自动填充对应的值,然后在发送给业务服务器。

    业务服务器在收到来自七牛的回调请求的时候,可以根据请求头部的Authorization字段来进行验证,查看该请求是否是来自七牛的未经篡改的请求,具体可以参考七牛的回调鉴权

    注意:业务端服务器回调鉴权的Content-Type类型应该与上传策略中指定的callbackBodyType相同,默认为 application/x-www-form-urlencoded,当 Content-Type 为 application/x-www-form-urlencoded 时,签名内容必须包括请求内容。当 Content-Type 为 application/json 时,签名内容不包括请求内容。

    /**
    <?php
        require_once __DIR__ . '/../autoload.php';
        use Qiniu\Auth;
        $accessKey = getenv('QINIU_ACCESS_KEY');
        $secretKey = getenv('QINIU_SECRET_KEY');
        $bucket = getenv('QINIU_TEST_BUCKET');
        $auth = new Auth($accessKey, $secretKey);
        //获取回调的body信息
        $callbackBody = file_get_contents('php://input');
        //回调的contentType
        $contentType = 'application/x-www-form-urlencoded';
        //回调的签名信息,可以验证该回调是否来自七牛
        $authorization = $_SERVER['HTTP_AUTHORIZATION'];
        //七牛回调的url,具体可以参考:http://developer.qiniu.com/docs/v6/api/reference/security/put-policy.html
        $url = 'http://172.30.251.210/upload_verify_callback.php';
        $isQiniuCallback = $auth->verifyCallback($contentType, $authorization, $url, $callbackBody);
        if ($isQiniuCallback) {
            $resp = array('ret' => 'success');
        } else {
            $resp = array('ret' => 'failed');
        }
        echo json_encode($resp);
    

    下载文件

    文件下载分为公开空间的文件下载和私有空间的文件下载。

    公开空间

    每个 bucket 都会绑定一个或多个域名 (domain)。如果这个 bucket 是公开的,那么该 bucket 中的所有文件可以通过一个公开的下载 url 访问:

    http://<domain>/<key>
    

    其中 domain 是 bucket 对应的域名。七牛云存储为每一个 bucket 提供一个默认域名。默认域名可以到七牛开发者平台中的存储空间查询。

    假设某个 bucket 既绑定了七牛的二级域名,如:hello.qiniudn.com,也绑定了自定义域名(需要备案),如:hello.com。那么该 bucket 中 key 为 test.mp4 的文件可以通过 http://hello.qiniudn.com/qiniu.mp4http://hello.com/qiniu.mp4 中任意一个 url 进行访问。

    下载私有文件

    如果某个 bucket 是私有的,那么这个 bucket 中的所有文件只能通过一个临时有效的 downloadUrl 访问:

    http://<domain>/<key>?e=<deadline>&token=<dntoken>
    

    其中 token 是由业务服务器签发的一个临时下载凭证,deadline 是其有效期。下载凭证不需要单独生成,php-SDK 提供了生成完整

    use Qiniu\Auth;
    
    $accessKey ="your accessKey";
    $secretKey = "your secretKey"
    
    // 构建Auth对象
    $auth = new Auth($accessKey, $secretKey);
    
    // 私有空间中的外链 http://<domain>/<file_key>
    $baseUrl = 'http://if-pri.qiniudn.com/qiniu.png?imageView2/1/h/500';
    // 对链接进行签名
    $signedUrl = $auth->privateDownloadUrl($baseUrl);
    
    echo $signedUrl;
    

    生成 downloadUrl 后,服务端下发 downloadUrl 给客户端。客户端收到 downloadUrl 后,和公有资源类似,直接用任意的 HTTP 客户端就可以下载该资源了。需要注意的是,在 downloadUrl 失效却还没有完成下载时,需要重新向服务器申请授权。

    资源管理

    资源管理包括的主要功能有: 资源管理包括对存储在七牛云存储上的文件进行查看、删除、复制和移动处理。同时七牛云存储也支持对文件进行相应的批量操作。

    获取文件信息

    $accessKey = getenv('QINIU_ACCESS_KEY');
    $secretKey = getenv('QINIU_SECRET_KEY');
    $bucket = getenv('QINIU_TEST_BUCKET');
    $key = "qiniu.mp4";
    $auth = new Auth($accessKey, $secretKey);
    $config = new \Qiniu\Config();
    $bucketManager = new \Qiniu\Storage\BucketManager($auth, $config);
    list($fileInfo, $err) = $bucketManager->stat($bucket, $key);
    if ($err) {
        print_r($err);
    } else {
        print_r($fileInfo);
    }
    

    修改文件MimeType

    $accessKey = getenv('QINIU_ACCESS_KEY');
    $secretKey = getenv('QINIU_SECRET_KEY');
    $bucket = getenv('QINIU_TEST_BUCKET');
    $key = 'qiniu.mp4';
    $newMime = 'video/x-mp4';
    
    $auth = new Auth($accessKey, $secretKey);
    $config = new \Qiniu\Config();
    $bucketManager = new \Qiniu\Storage\BucketManager($auth, $config);
    
    $err = $bucketManager->changeMime($bucket, $key, $newMime);
    if ($err) {
        print_r($err);
    }
    

    修改文件存储类型

    $accessKey = getenv('QINIU_ACCESS_KEY');
    $secretKey = getenv('QINIU_SECRET_KEY');
    $bucket = getenv('QINIU_TEST_BUCKET');
    
    $key = "qiniu.mp4";
    $auth = new Auth($accessKey, $secretKey);
    $config = new \Qiniu\Config();
    $bucketManager = new \Qiniu\Storage\BucketManager($auth, $config);
    
    $fileType = 1;//0 表示普通存储,1表示低频存储
    
    $err = $bucketManager->changeType($bucket, $key, $fileType);
    if ($err) {
        print_r($err);
    }
    

    移动或重命名文件

    移动操作本身支持移动文件到相同,不同空间中,在移动的同时也可以支持文件重命名。唯一的限制条件是,移动的源空间和目标空间必须在同一个机房。

    源空间 目标空间 源文件名 目标文件名 描述
    BucketA BucketA KeyA KeyB 相当于同空间文件重命名
    BucketA BucketB KeyA KeyA 移动文件到BucketB,文件名一致
    BucketA BucketB KeyA KeyB 移动文件到BucketB,文件名变成KeyB

    move操作支持强制覆盖选项,即如果目标文件已存在,可以设置强制覆盖选项force来覆盖那个文件的内容。

    $accessKey = getenv('QINIU_ACCESS_KEY');
    $secretKey = getenv('QINIU_SECRET_KEY');
    $bucket = getenv('QINIU_TEST_BUCKET');
    $key = "qiniu.mp4";
    $auth = new Auth($accessKey, $secretKey);
    $config = new \Qiniu\Config();
    $bucketManager = new \Qiniu\Storage\BucketManager($auth, $config);
    
    $srcBucket = $bucket;
    $destBucket = $bucket;
    $srcKey = $key . "_copy";
    $destKey = $key . "_move";
    $err = $bucketManager->move($srcBucket, $srcKey, $destBucket, $destKey, true);
    if ($err) {
        print_r($err);
    }
    

    复制文件副本

    文件的复制和文件移动其实操作一样,主要的区别是移动后源文件不存在了,而复制的结果是源文件还存在,只是多了一个新的文件副本。

    $accessKey = getenv('QINIU_ACCESS_KEY');
    $secretKey = getenv('QINIU_SECRET_KEY');
    $bucket = getenv('QINIU_TEST_BUCKET');
    $key = "qiniu.mp4";
    $auth = new Auth($accessKey, $secretKey);
    $config = new \Qiniu\Config();
    $bucketManager = new \Qiniu\Storage\BucketManager($auth, $config);
    
    $srcBucket = $bucket;
    $destBucket = $bucket;
    $srcKey = $key;
    $destKey = $key . "_copy";
    $err = $bucketManager->copy($srcBucket, $srcKey, $destBucket, $destKey, true);
    if ($err) {
        print_r($err);
    }
    

    删除空间中的文件

    $accessKey = getenv('QINIU_ACCESS_KEY');
    $secretKey = getenv('QINIU_SECRET_KEY');
    $bucket = getenv('QINIU_TEST_BUCKET');
    
    $key = "qiniu.mp4_copy";
    $auth = new Auth($accessKey, $secretKey);
    $config = new \Qiniu\Config();
    $bucketManager = new \Qiniu\Storage\BucketManager($auth, $config);
    $err = $bucketManager->delete($bucket, $key);
    if ($err) {
        print_r($err);
    }
    

    设置或更新文件的生存时间

    可以给已经存在于空间中的文件设置文件生存时间,或者更新已设置了生存时间但尚未被删除的文件的新的生存时间。

    
    $accessKey = getenv('QINIU_ACCESS_KEY');
    $secretKey = getenv('QINIU_SECRET_KEY');
    $bucket = getenv('QINIU_TEST_BUCKET');
    
    $key = 'qiniu.mp4';
    $days = 10;
    
    $auth = new Auth($accessKey, $secretKey);
    $config = new \Qiniu\Config();
    $bucketManager = new \Qiniu\Storage\BucketManager($auth, $config);
    
    $err = $bucketManager->deleteAfterDays($bucket, $key, $days);
    if ($err) {
        print_r($err);
    }
    

    获取指定空间的文件列表

    $accessKey = getenv('QINIU_ACCESS_KEY');
    $secretKey = getenv('QINIU_SECRET_KEY');
    $bucket = getenv('QINIU_TEST_BUCKET');
    $auth = new Auth($accessKey, $secretKey);
    $bucketManager = new BucketManager($auth);
    
    // 要列取文件的公共前缀
    $prefix = '';
    
    // 上次列举返回的位置标记,作为本次列举的起点信息。
    $marker = '';
    
    // 本次列举的条目数
    $limit = 100;
    
    $delimiter = '/';
    
    // 列举文件
    list($ret, $err) = $bucketManager->listFiles($bucket, $prefix, $marker, $limit, $delimiter);
    if ($err !== null) {
        echo "\n====> list file err: \n";
        var_dump($err);
    } else {
        if (array_key_exists('marker', $ret)) {
            echo "Marker:" . $ret["marker"] . "\n";
        }
        echo "\nList Iterms====>\n";
        //var_dump($ret['items']);
    }
    

    抓取网络资源到空间

    $accessKey = getenv('QINIU_ACCESS_KEY');
    $secretKey = getenv('QINIU_SECRET_KEY');
    $bucket = getenv('QINIU_TEST_BUCKET');
    $auth = new Auth($accessKey, $secretKey);
    $bucketManager = new BucketManager($auth);
    
    $url = 'http://devtools.qiniu.com/qiniu.png';
    $key = time() . '.png';
    
    // 指定抓取的文件保存名称
    list($ret, $err) = $bucketManager->fetch($url, $bucket, $key);
    echo "=====> fetch $url to bucket: $bucket  key: $key\n";
    if ($err !== null) {
        var_dump($err);
    } else {
        print_r($ret);
    }
    
    // 不指定key时,以文件内容的hash作为文件名
    $key = null;
    list($ret, $err) = $bucketManager->fetch($url, $bucket, $key);
    echo "=====> fetch $url to bucket: $bucket  key: $(etag)\n";
    if ($err !== null) {
        var_dump($err);
    } else {
        print_r($ret);
    }
    

    更新镜像空间中存储的文件内容

    $accessKey = getenv('QINIU_ACCESS_KEY');
    $secretKey = getenv('QINIU_SECRET_KEY');
    $bucket = getenv('QINIU_TEST_BUCKET');
    
    $key = "qiniu.mp4";
    $auth = new Auth($accessKey, $secretKey);
    $config = new \Qiniu\Config();
    $bucketManager = new \Qiniu\Storage\BucketManager($auth, $config);
    $err = $bucketManager->prefetch($bucket, $key);
    if ($err) {
        print_r($err);
    }
    

    资源管理批量操作

    批量获取文件信息

    $accessKey = getenv('QINIU_ACCESS_KEY');
    $secretKey = getenv('QINIU_SECRET_KEY');
    $bucket = getenv('QINIU_TEST_BUCKET');
    
    $auth = new Auth($accessKey, $secretKey);
    $config = new \Qiniu\Config();
    $bucketManager = new \Qiniu\Storage\BucketManager($auth, $config);
    
    //每次最多不能超过1000个
    $keys = array(
        'qiniu.mp4',
        'qiniu.png',
        'qiniu.jpg'
    );
    
    $ops = $bucketManager->buildBatchStat($bucket, $keys);
    list($ret, $err) = $bucketManager->batch($ops);
    if ($err) {
        print_r($err);
    } else {
        print_r($ret);
    }
    

    批量修改文件类型

    $accessKey = getenv('QINIU_ACCESS_KEY');
    $secretKey = getenv('QINIU_SECRET_KEY');
    $bucket = getenv('QINIU_TEST_BUCKET');
    
    $auth = new Auth($accessKey, $secretKey);
    $config = new \Qiniu\Config();
    $bucketManager = new \Qiniu\Storage\BucketManager($auth, $config);
    
    //每次最多不能超过1000个
    $keys = array(
        'qiniu.mp4',
        'qiniu.png',
        'qiniu.jpg'
    );
    
    $keyTypePairs = array();
    //type=0表示普通存储,type=1表示低频存储
    foreach ($keys as $key) {
        $keyTypePairs[$key] = 1;
    }
    
    $ops = $bucketManager->buildBatchChangeType($bucket, $keyTypePairs);
    list($ret, $err) = $bucketManager->batch($ops);
    if ($err) {
        print_r($err);
    } else {
        print_r($ret);
    }
    

    批量删除文件

    $accessKey = getenv('QINIU_ACCESS_KEY');
    $secretKey = getenv('QINIU_SECRET_KEY');
    $bucket = getenv('QINIU_TEST_BUCKET');
    $auth = new Auth($accessKey, $secretKey);
    $config = new \Qiniu\Config();
    $bucketManager = new \Qiniu\Storage\BucketManager($auth, $config);
    
    //每次最多不能超过1000个
    $keys = array(
        'qiniu.mp4',
        'qiniu.png',
        'qiniu.jpg'
    );
    
    $ops = $bucketManager->buildBatchDelete($bucket, $keys);
    list($ret, $err) = $bucketManager->batch($ops);
    if ($err) {
        print_r($err);
    } else {
        print_r($ret);
    }
    

    批量复制文件

    $accessKey = getenv('QINIU_ACCESS_KEY');
    $secretKey = getenv('QINIU_SECRET_KEY');
    $bucket = getenv('QINIU_TEST_BUCKET');
    
    $auth = new Auth($accessKey, $secretKey);
    $config = new \Qiniu\Config();
    $bucketManager = new \Qiniu\Storage\BucketManager($auth, $config);
    
    //每次最多不能超过1000个
    $keys = array(
        'qiniu.mp4',
        'qiniu.png',
        'qiniu.jpg'
    );
    
    $keyPairs = array();
    foreach ($keys as $key) {
        $keyPairs[$key] = $key . "_copy";
    }
    $srcBucket = $bucket;
    $destBucket = $bucket;
    
    $ops = $bucketManager->buildBatchCopy($srcBucket, $keyPairs, $destBucket, true);
    list($ret, $err) = $bucketManager->batch($ops);
    if ($err) {
        print_r($err);
    } else {
        print_r($ret);
    }
    

    批量移动或重命名文件

    $accessKey = getenv('QINIU_ACCESS_KEY');
    $secretKey = getenv('QINIU_SECRET_KEY');
    $bucket = getenv('QINIU_TEST_BUCKET');
    
    $auth = new Auth($accessKey, $secretKey);
    $config = new \Qiniu\Config();
    $bucketManager = new \Qiniu\Storage\BucketManager($auth, $config);
    
    //每次最多不能超过1000个
    $keys = array(
        'qiniu.mp4',
        'qiniu.png',
        'qiniu.jpg'
    );
    
    $keyPairs = array();
    foreach ($keys as $key) {
        $keyPairs[$key . "_copy"] = $key . "_move";
    }
    
    $srcBucket = $bucket;
    $destBucket = $bucket;
    
    $ops = $bucketManager->buildBatchMove($srcBucket, $keyPairs, $destBucket, true);
    list($ret, $err) = $bucketManager->batch($ops);
    if ($err) {
        print_r($err);
    } else {
        print_r($ret);
    }
    

    批量更新文件的有效期

    $accessKey = getenv('QINIU_ACCESS_KEY');
    $secretKey = getenv('QINIU_SECRET_KEY');
    $bucket = getenv('QINIU_TEST_BUCKET');
    $auth = new Auth($accessKey, $secretKey);
    $config = new \Qiniu\Config();
    $bucketManager = new \Qiniu\Storage\BucketManager($auth, $config);
    
    //每次最多不能超过1000个
    $keys = array(
        'qiniu.mp4',
        'qiniu.png',
        'qiniu.jpg'
    );
    
    $keyDayPairs = array();
    //day=0表示永久存储
    foreach ($keys as $key) {
        $keyDayPairs[$key] = 0;
    }
    
    $ops = $bucketManager->buildBatchDeleteAfterDays($bucket, $keyDayPairs);
    list($ret, $err) = $bucketManager->batch($ops);
    if ($err) {
        print_r($err);
    } else {
        print_r($ret);
    }
    

    批量更新文件存储类型

    $accessKey = getenv('QINIU_ACCESS_KEY');
    $secretKey = getenv('QINIU_SECRET_KEY');
    $bucket = getenv('QINIU_TEST_BUCKET');
    
    $auth = new Auth($accessKey, $secretKey);
    $config = new \Qiniu\Config();
    $bucketManager = new \Qiniu\Storage\BucketManager($auth, $config);
    
    //每次最多不能超过1000个
    $keys = array(
        'qiniu.mp4',
        'qiniu.png',
        'qiniu.jpg'
    );
    
    $keyTypePairs = array();
    //type=0表示普通存储,type=1表示低频存储
    foreach ($keys as $key) {
        $keyTypePairs[$key] = 1;
    }
    
    $ops = $bucketManager->buildBatchChangeType($bucket, $keyTypePairs);
    list($ret, $err) = $bucketManager->batch($ops);
    if ($err) {
        print_r($err);
    } else {
        print_r($ret);
    }
    

    持久化数据处理

    发送数据处理请求

    对于已经保存到七牛空间的文件,可以通过发送持久化的数据处理指令来进行处理,这些指令支持七牛官方提供的指令,也包括客户自己开发的自定义数据处理的指令。数据处理的结果还可以通过七牛主动通知的方式告知业务服务器。

    
    use Qiniu\Auth;
    use Qiniu\Processing\PersistentFop;
    
    //对已经上传到七牛的视频发起异步转码操作
    
    $accessKey = getenv('QINIU_ACCESS_KEY');
    $secretKey = getenv('QINIU_SECRET_KEY');
    $bucket = getenv('QINIU_TEST_BUCKET');
    
    $auth = new Auth($accessKey, $secretKey);
    
    //要转码的文件所在的空间和文件名。
    $key = 'qiniu.mp4';
    
    //转码是使用的队列名称。 https://portal.qiniu.com/mps/pipeline
    $pipeline = 'sdktest';
    $force = false;
    
    //转码完成后通知到你的业务服务器。
    $notifyUrl = 'http://375dec79.ngrok.com/notify.php';
    $config = new \Qiniu\Config();
    //$config->useHTTPS=true;
    
    $pfop = new PersistentFop($auth, $config);
    
    //要进行转码的转码操作。 http://developer.qiniu.com/docs/v6/api/reference/fop/av/avthumb.html
    $fops = "avthumb/mp4/s/640x360/vb/1.4m|saveas/" . \Qiniu\base64_urlSafeEncode($bucket . ":qiniu_640x360.mp4");
    
    list($id, $err) = $pfop->execute($bucket, $key, $fops, $pipeline, $notifyUrl, $force);
    echo "\n====> pfop avthumb result: \n";
    if ($err != null) {
        var_dump($err);
    } else {
        echo "PersistentFop Id: $id\n";
    }
    
    //查询转码的进度和状态
    list($ret, $err) = $pfop->status($id);
    echo "\n====> pfop avthumb status: \n";
    if ($err != null) {
        var_dump($err);
    } else {
        var_dump($ret);
    }
    

    CDN相关功能

    文件刷新

    use \Qiniu\Cdn\CdnManager;
    $accessKey = getenv('QINIU_ACCESS_KEY');
    $secretKey = getenv('QINIU_SECRET_KEY');
    
    $auth = new Qiniu\Auth($accessKey, $secretKey);
    
    //待刷新的文件列表和目录,文件列表最多一次100个,目录最多一次10个
    //参考文档:http://developer.qiniu.com/article/fusion/api/refresh.html
    $urls = array(
        "http://phpsdk.qiniudn.com/qiniu.jpg",
        "http://phpsdk.qiniudn.com/qiniu2.jpg",
    );
    
    //刷新目录需要联系七牛技术支持开通账户权限
    $dirs = array(
        "http://phpsdk.qiniudn.com/test/"
    );
    
    $cdnManager = new CdnManager($auth);
    
    // 目前客户默认没有目录刷新权限,刷新会有400038报错,参考:https://developer.qiniu.com/fusion/api/1229/cache-refresh
    // 需要刷新目录请工单联系技术支持 https://support.qiniu.com/tickets/category
    list($refreshResult, $refreshErr) = $cdnManager->refreshUrlsAndDirs($urls, $dirs);
    if ($refreshErr != null) {
        var_dump($refreshErr);
    } else {
        echo "refresh request sent\n";
        print_r($refreshResult);
    }
    
    //如果只有刷新链接或者目录的需求,可以分布使用
    
    list($refreshResult, $refreshErr) = $cdnManager->refreshUrls($urls);
    if ($refreshErr != null) {
        var_dump($refreshErr);
    } else {
        echo "refresh request sent\n";
        print_r($refreshResult);
    }
    
    list($refreshResult, $refreshErr) = $cdnManager->refreshDirs($dirs);
    if ($refreshErr != null) {
        var_dump($refreshErr);
    } else {
        echo "refresh request sent\n";
        print_r($refreshResult);
    }
    

    文件预取

    $accessKey = getenv('QINIU_ACCESS_KEY');
    $secretKey = getenv('QINIU_SECRET_KEY');
    
    $auth = new Qiniu\Auth($accessKey, $secretKey);
    
    //待预取的文件列表,文件列表最多一次100个,目录最多一次10个
    //参考文档:http://developer.qiniu.com/article/fusion/api/prefetch.html
    $urls = array(
        "http://phpsdk.qiniudn.com/qiniu.jpg",
        "http://phpsdk.qiniudn.com/qiniu2.jpg",
    );
    
    $cdnManager = new CdnManager($auth);
    
    list($refreshResult, $refreshErr) = $cdnManager->prefetchUrls($urls);
    if ($prefetchErr != null) {
        var_dump($prefetchErr);
    } else {
        echo "prefetch request sent\n";
        print_r($prefetchResult);
    }
    

    获取域名流量

    具体获取域名流量带宽参数详解可以参考 流量带宽

    $accessKey = getenv('QINIU_ACCESS_KEY');
    $secretKey = getenv('QINIU_SECRET_KEY');
    
    $auth = new Qiniu\Auth($accessKey, $secretKey);
    $cdnManager = new CdnManager($auth);
    
    //参考文档:http://developer.qiniu.com/article/fusion/api/traffic-bandwidth.html
    
    $domains = array(
        "javasdk.qiniudn.com",
        "phpsdk.qiniudn.com"
    );
    
    $startDate = "2017-08-20";
    $endDate = "2017-08-21";
    
    //5min or hour or day
    $granularity = "day";
    

    获取域名带宽

    $accessKey = getenv('QINIU_ACCESS_KEY');
    $secretKey = getenv('QINIU_SECRET_KEY');
    
    $auth = new Qiniu\Auth($accessKey, $secretKey);
    $cdnManager = new CdnManager($auth);
    
    //获取带宽数据
    list($bandwidthData, $getBandwidthErr) = $cdnManager->getBandwidthData(
        $domains,
        $startDate,
        $endDate,
        $granularity
    );
    
    if ($getBandwidthErr != null) {
        var_dump($getBandwidthErr);
    } else {
        echo "get bandwidth data success\n";
        print_r($bandwidthData);
    }
    

    获取日志下载链接

    具体日志下载链接参数详解可以参考 日志下载

    $accessKey = getenv('QINIU_ACCESS_KEY');
    $secretKey = getenv('QINIU_SECRET_KEY');
    
    $auth = new Qiniu\Auth($accessKey, $secretKey);
    $cdnManager = new CdnManager($auth);
    
    $domains = array(
        "javasdk.qiniudn.com",
        "phpsdk.qiniudn.com"
    );
    
    $logDate = '2017-08-20';
    
    //获取日志下载链接
    //参考文档:http://developer.qiniu.com/article/fusion/api/log.html
    
    list($logListData, $getLogErr) = $cdnManager->getCdnLogList($domains, $logDate);
    if ($getLogErr != null) {
        var_dump($getLogErr);
    } else {
        echo "get cdn log list success\n";
        print_r($logListData);
    }
    

    构建时间戳防盗链访问链接

    具体算法可以参考:时间戳防盗链

    use \Qiniu\Cdn\CdnManager;
    
    //创建时间戳防盗链
    //时间戳防盗链密钥,后台获取
    $encryptKey = 'your_domain_timestamp_antileech_encryptkey';
    
    //带访问协议的域名
    $url1 = 'http://phpsdk.qiniuts.com/24.jpg?avinfo';
    $url2 = 'http://phpsdk.qiniuts.com/24.jpg';
    
    //有效期时间(单位秒)
    $durationInSeconds = 3600;
    
    $signedUrl = CdnManager::createTimestampAntiLeechUrl($url1, $encryptKey, $durationInSeconds);
    print($signedUrl);
    

    API 参考

    常见问题

    • PHP-SDK的callback保留了请求的错误信息,回复信息和头部信息,遇到问题时,可以都打印出来提交给我们排查问题。
    • API 的使用,可以参考我们为大家精心准备的使用实例

    相关资源

    如果您有任何关于我们文档或产品的建议和想法,欢迎您通过以下方式与我们互动讨论:

    • 技术论坛 - 在这里您可以和其他开发者愉快的讨论如何更好的使用七牛云服务
    • 提交工单 - 如果您的问题不适合在论坛讨论或希望及时解决,您也可以提交一个工单,我们的技术支持人员会第一时间回复您
    • 博客 - 这里会持续更新发布市场活动和技术分享文章
    • 微博
    • 常见问题

    贡献代码

    1. Fork

    2. 创建您的特性分支 git checkout -b my-new-feature

    3. 提交您的改动 git commit -am 'Added some feature'

    4. 将您的修改记录提交到远程 git 仓库 git push origin my-new-feature

    5. 然后到 github 网站的该 git 远程仓库的 my-new-feature 分支下发起 Pull Request

    许可证

    Copyright (c) 2014 qiniu.com

    基于 MIT 协议发布:

    以上内容是否对您有帮助?
  • 提交工单