添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
相关文章推荐
呐喊的生姜  ·  Day07 - [豐收款] ...·  8 月前    · 
腹黑的橙子  ·  Package Deployment ...·  1 年前    · 
  • 开发指南
    1. 安全机制
      1. 上传策略
      2. 上传凭证
      3. 下载凭证
      4. 管理凭证
        1. 管理凭证历史文档
    2. 上传资源
      1. 表单上传
      2. 分片上传 v1 版
      3. 分片上传 v2 版
      4. 简单反馈
      5. 回调通知
      6. 303 重定向
      7. 异步数据预处理
      8. 自定义响应内容
      9. 变量
    3. 下载资源
      1. 公开资源下载
      2. 私有资源下载
      3. 防盗链
      4. 下载设置
      5. 高级下载
    4. 管理存储空间
      1. 绑定源站域名
      2. 访问控制
      3. 静态页面管理
      4. 空间备注
      5. 文件客户端缓存
      6. 重定向
      7. 空间标签
      8. 空间授权
      9. 跨域资源共享
      10. 生命周期管理
      11. 事件通知
      12. 镜像回源
      13. 空间清单
      14. 跨区域同步
      15. 空间访问日志
      16. 删除空间
    5. 数据安全
      1. Referer 防盗链
      2. 对象锁定
    6. 数据处理
      1. 图片处理
      2. 实时转码(边转边播)
      3. 原始资源保护
      4. 数据工作流
      5. 图片压缩格式自适应
      6. CDN 热点视频瘦身
    7. 传输加速
    8. AWS S3 兼容
      1. 存储类型
      2. 服务域名
      3. 签名认证
      4. 临时安全凭证
      5. 兼容公共头
      6. 兼容 API
        1. 使用 Bucket Policy 授权
      7. 兼容 SDK 示例
        1. AWS SDK for C++
        2. AWS SDK for .NET
        3. AWS SDK for Go
        4. AWS SDK for Java
        5. AWS SDK for JavaScript
        6. AWS SDK for Kotlin
        7. AWS SDK for PHP
        8. AWS SDK for Python
        9. AWS SDK for Ruby
        10. AWS SDK for Rust
        11. AWS SDK for Swift
      8. 兼容工具示例
        1. AWS CLI
        2. CloudBerry Explorer
        3. S3 Browser
        4. S3FS
    9. 附录
  • 控制台指南
    1. 控制台概览
    2. 空间管理
      1. 新建空间
      2. 空间列表管理
      3. 空间概览
      4. 空间设置
        1. 设置访问控制
        2. 设置静态页面
        3. 设置空间备注
        4. 设置文件客户端缓存
        5. 设置重定向
        6. 设置标签管理
        7. 设置空间授权
        8. 设置Referer防盗链
        9. 设置跨域资源共享
        10. 设置生命周期
        11. 设置事件通知
        12. 设置镜像回源
        13. 设置空间清单
        14. 设置对象锁定
        15. 设置空间日志
        16. 设置空间内容审核
        17. 设置传输加速
        18. 删除存储空间
      5. 域名管理
        1. 设置自定义CDN加速域名
        2. 设置自定义源站域名
      6. 数据处理
        1. 多媒体样式
          1. 设置图片样式
          2. 设置视频样式
          3. 设置原始资源保护
        2. 任务与工作流
          1. 任务管理
          2. 任务触发器
          3. 工作流模板
          4. 预设集管理
            1. 普通转码
            2. 锐智转码
            3. 视频水印
            4. 视频截图
            5. 音视频拼接
    3. 文件管理
      1. 上传文件
      2. 创建目录
      3. 搜索文件
      4. 修改文件名
      5. 修改文件类型
      6. 查看文件详情
      7. 设置文件元信息
      8. 下载文件
      9. 分享文件
      10. 分享目录
      11. 刷新 CDN 缓存
      12. 移动文件
      13. 删除文件
      14. 删除目录
      15. 修改文件存储类型
      16. 解冻文件
      17. 任务中心
    4. 设置跨区域同步
    5. 统计分析
    6. 存储安全
      1. 内容审核
      2. 违规列表
    7. 设置数据迁移
  • API 文档
  • API 概览
  • HTTP Headers
  • 错误响应
  • 数据格式
  • Service 接口
    1. 获取 Bucket 列表
  • Bucket 接口
    1. 创建 Bucket
    2. 删除 Bucket
    3. 获取 Bucket 空间域名
    4. 设置 Bucket 访问权限
    5. 设置空间标签
    6. 查询空间标签
    7. 删除空间标签
  • Object 接口
    1. 直传文件
    2. 分片上传 v1 版
      1. 创建块
      2. 上传片
      3. 创建文件
    3. 分片上传 v2 版
      1. 初始化任务
      2. 分块上传数据
      3. 完成文件上传
      4. 终止上传
      5. 列举已上传分片
    4. 资源列举
    5. 资源元信息查询
    6. 资源元信息修改
    7. 资源移动/重命名
    8. 资源复制
    9. 资源删除
    10. 批量操作
    11. 修改文件状态
    12. 修改文件存储类型
    13. 解冻归档/深度归档存储文件
    14. 修改文件过期删除时间
    15. 修改文件生命周期
    16. 镜像资源更新
    17. 异步第三方资源抓取
  • 数据统计接口
  • SDK 下载
  • 鸿蒙(Harmony) SDK
  • Android SDK
    1. Android SDK历史文档
      1. Android SDK V7
  • C/C++ SDK
  • C# SDK
    1. C# SDK v7.2.15 文档
    2. C# SDK v7.0 文档
    3. C# SDK v6 文档
  • Flutter SDK
  • Go SDK
    1. Go SDK历史版本
  • Java SDK
    1. Java SDK 历史文档
  • JavaScript SDK
    1. JavaScript SDK历史文档2.x
    2. JavaScript SDK历史文档1.x
  • Node.js SDK
    1. Node.js SDK V6
  • Objective-C SDK
  • PHP SDK
    1. PHP SDK历史文档
  • Python SDK
  • Ruby SDK
  • Rust SDK
  • SDK 隐私政策
  • 图形化工具 Kodo Browser
  • 命令行工具 Qshell
  • 数据迁移工具 Kodoimport
  • 检测工具
    1. 上传测试页面
    2. 网络检测工具 Qwebtest
  • Qiniu Jenkins Plugin
  • 数据安全最佳实践
    1. 保障安全上传、下载、管理数据
    2. 降低因账号密码泄露带来的未授权访问风险
    3. 降低被恶意篡改数据的风险
    4. 防止恶意文件上传
    5. 降低被恶意访问、盗量的风险
    6. 降低或因误操作导致的数据丢失的风险
    7. 跟踪、追溯对数据的关键操作
    8. 敏感数据安全防护
  • 文件系统挂载存储桶
  • 在容器中挂载存储桶
  • 数据备份
  • 数据迁移
    1. 热数据无缝迁移
    2. 本地数据迁移至 Kodo
    3. 以 URL 作为源地址的数据迁移至 Kodo
    4. 第三方云存储数据迁移至 Kodo
  • 开源软件管理对象存储
    1. 使用 Go CDK 对接对象存储 Kodo
      1. 使用七牛 Go CDK Driver 对接对象存储 Kodo
      2. 使用 Go CDK 通过 S3 协议对接对象存储 Kodo
    2. 使用 Hadoop 管理对象存储 Kodo
      1. 使用 Hadoop S3A 客户端管理对象存储 Kodo
      2. 使用 Hadoop-Kodo 插件管理对象存储 Kodo
    3. 使用 Kubernetes CSI 挂载对象存储 Kodo
    4. 使用 Rclone 命令行工具管理对象存储 Kodo
    5. 使用 Restic 备份工具对接对象存储 Kodo
    6. 使用 Terraform 管理对象存储 Kodo
  • 此 SDK 适用于 Java 8 及以上版本。使用此 SDK 构建您的网络应用程序,能让您以非常便捷地方式将数据安全地存储到 七牛云 上。无论您的网络应用是一个网站程序,还是包括从云端(服务端程序)到终端(手持设备应用)的架构服务或应用,通过 七牛云 及其 SDK,都能让您应用程序的终端用户高速上传和下载,同时也让您的服务端更加轻盈。

    Java SDK 属于 七牛 服务端 SDK 之一,主要有如下功能:

  • 提供生成客户端上传所需的上传凭证的功能
  • 提供文件从服务端直接上传 七牛 的功能
  • 提供对 七牛 空间中文件进行管理的功能
  • 提供对 七牛 空间中文件进行处理的功能
  • 提供七牛融合 CDN 相关的刷新,预取,日志功能
  • 提供七牛视频监控 QVS 设备管理、流管理等功能
  • Java SDK 项目地址
  • Java SDK 发布地址
  • Java SDK 历史文档
  • 使用 Gradle
  • 使用 Maven
  • 从 7.2.24 开始,okhttp3 升级到 3.14.2,其要求 java 1.8 及以上。
  • 若为 java 1.7 ,请手动指定 okhttp3 依赖 3.12,要求 3.12.3 及以上, com.squareup.okhttp3:okhttp:3.12.3
  •     compile ('com.qiniu:qiniu-java-sdk:7.16.0') {
            exclude group: 'com.squareup.okhttp3', module: 'okhttp'
        compile 'com.squareup.okhttp3:okhttp:3.12.6'
    

    Gradle

    compile 'com.qiniu:qiniu-java-sdk:7.16.+'
    

    Maven

    <dependency>
      <groupId>com.qiniu</groupId>
      <artifactId>qiniu-java-sdk</artifactId>
      <version>[7.16.0, 7.16.99]</version>
    </dependency>
    

    这里的version指定了一个版本范围,每次更新pom.xml的时候会尝试去下载7.16.x版本中的最新版本,你可以手动指定一个固定的版本。

    请尽量使用包管理工具自动解决依赖问题。如果条件实在不满足,只能通过手动下载 jar 包的方式来解决。本项目自身 jar 及依赖的第三方库如下:

    Java SDK 依赖的第三方库及其版本如下:

    <dependencies>
        <dependency>
          <groupId>com.squareup.okhttp3</groupId>
          <artifactId>okhttp</artifactId>
          <version>3.14.2</version>
          <scope>compile</scope>
        </dependency>
        <dependency>
          <groupId>com.google.code.gson</groupId>
          <artifactId>gson</artifactId>
          <version>2.8.5</version>
          <scope>compile</scope>
        </dependency>
        <dependency>
          <groupId>com.qiniu</groupId>
          <artifactId>happy-dns-java</artifactId>
          <version>0.1.6</version>
          <scope>test</scope>
        </dependency>
        <dependency>
          <groupId>junit</groupId>
          <artifactId>junit</artifactId>
          <version>4.12</version>
          <scope>test</scope>
        </dependency>
      </dependencies>
    

    Java SDK 的所有的功能,都需要合法的授权。授权凭证的签算需要七牛 账号下的一对有效的Access KeySecret Key,这对密钥可以通过如下步骤获得:

  • 点击注册 🔗开通七牛开发者帐号
  • 如果已有账号,直接登录七牛开发者后台,点击这里 🔗查看 Access Key 和 Secret Key
  • 客户端上传凭证
  • 简单上传凭证
  • 覆盖上传凭证
  • 自定义上传回复凭证
  • 带回调业务服务器的凭证
  • 带数据处理的凭证
  • 带自定义参数的凭证
  • 综合上传凭证
  • 服务器直传
  • 构建配置类
  • 自定义上传域名
  • 设置请求协议为 http
  • 字节数组上传
  • 数据流上传
  • 自定义参数上传
  • 解析自定义回复内容
  • 业务服务器验证存储服务回调
  • 文件上传分为客户端上传(主要是指网页端和移动端等面向终端用户的场景)和服务端上传两种场景,具体可以参考文档业务流程

  • 客户端上传:Java 编写的服务端仅提供上传需要的凭证,网页端和移动端等客户端从服务端获取此凭证后使用客户端相应的 SDK 进行上传操作
  • 服务端上传:文件在服务端或者服务端作为文件的中转站,使用此 Java SDK 上传文件至七牛云端
  • 服务端 SDK 在上传方面主要提供两种功能

  • 生成客户端上传所需要的上传凭证
  • 服务端上传文件到七牛云端
  • 客户端上传凭证

    客户端(移动端或者 Web 端)上传文件的时候,需要从客户自己的业务服务器获取上传凭证,而这些上传凭证是通过服务端的 SDK 来生成的,然后通过客户自己的业务 API 分发给客户端使用。根据上传的业务需求不同,七牛云Java SDK 支持丰富的上传凭证生成方式。

    简单上传的凭证

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

    String accessKey = "access key";
    String secretKey = "secret key";
    String bucket = "bucket name";
    Auth auth = Auth.create(accessKey, secretKey);
    String upToken = auth.uploadToken(bucket);
    System.out.println(upToken);
    

    覆盖上传的凭证

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

    String accessKey = "access key";
    String secretKey = "secret key";
    String bucket = "bucket name";
    String key = "file key";
    Auth auth = Auth.create(accessKey, secretKey);
    String upToken = auth.uploadToken(bucket, key);
    System.out.println(upToken);
    

    自定义上传回复的凭证

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

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

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

    String accessKey = "access key";
    String secretKey = "secret key";
    String bucket = "bucket name";
    Auth auth = Auth.create(accessKey, secretKey);
    StringMap putPolicy = new StringMap();
    putPolicy.put("returnBody", "{\"key\":\"$(key)\",\"hash\":\"$(etag)\",\"bucket\":\"$(bucket)\",\"fsize\":$(fsize)}");
    long expireSeconds = 3600;
    String upToken = auth.uploadToken(bucket, null, expireSeconds, putPolicy);
    System.out.println(upToken);
    

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

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

    带回调业务服务器的凭证

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

    String accessKey = "access key";
    String secretKey = "secret key";
    String bucket = "bucket name";
    Auth auth = Auth.create(accessKey, secretKey);
    StringMap putPolicy = new StringMap();
    putPolicy.put("callbackUrl", "http://api.example.com/qiniu/upload/callback");
    putPolicy.put("callbackBody", "{\"key\":\"$(key)\",\"hash\":\"$(etag)\",\"bucket\":\"$(bucket)\",\"fsize\":$(fsize)}");
    putPolicy.put("callbackBodyType", "application/json");
    long expireSeconds = 3600;
    String upToken = auth.uploadToken(bucket, null, expireSeconds, putPolicy);
    System.out.println(upToken);
    

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

    String accessKey = "access key";
    String secretKey = "secret key";
    String bucket = "bucket name";
    Auth auth = Auth.create(accessKey, secretKey);
    StringMap putPolicy = new StringMap();
    putPolicy.put("callbackUrl", "http://api.example.com/qiniu/upload/callback");
    putPolicy.put("callbackBody", "key=$(key)&hash=$(etag)&bucket=$(bucket)&fsize=$(fsize)");
    long expireSeconds = 3600;
    String upToken = auth.uploadToken(bucket, null, expireSeconds, putPolicy);
    System.out.println(upToken);
    

    带数据处理的凭证

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

    String accessKey = "access key";
    String secretKey = "secret key";
    String bucket = "bucket name";
    Auth auth = Auth.create(accessKey, secretKey);
    StringMap putPolicy = new StringMap();
    //数据处理指令,支持多个指令
    String saveMp4Entry = String.format("%s:avthumb_test_target.mp4", bucket);
    String saveJpgEntry = String.format("%s:vframe_test_target.jpg", bucket);
    String avthumbMp4Fop = String.format("avthumb/mp4|saveas/%s", UrlSafeBase64.encodeToString(saveMp4Entry));
    String vframeJpgFop = String.format("vframe/jpg/offset/1|saveas/%s", UrlSafeBase64.encodeToString(saveJpgEntry));
    //将多个数据处理指令拼接起来
    String persistentOpfs = StringUtils.join(new String[]{
            avthumbMp4Fop, vframeJpgFop
    }, ";");
    putPolicy.put("persistentOps", persistentOpfs);
    //数据处理队列名称
    putPolicy.put("persistentPipeline", "mps-pipe1");
    //任务类型:0: 普通任务 1: 闲时任务,配置闲时任务时 persistentPipeline 不可配置
    putPolicy.put("persistentType", 1);
    //数据处理完成结果通知地址
    putPolicy.put("persistentNotifyUrl", "http://api.example.com/qiniu/pfop/notify");
    long expireSeconds = 3600;
    String upToken = auth.uploadToken(bucket, null, expireSeconds, putPolicy);
    System.out.println(upToken);
    
  • 队列 pipeline 请参阅创建私有队列;转码操作具体参数请参阅音视频转码;saveas 请参阅处理结果另存
  • 闲时任务的功能介绍、使用场景、定价,详见 闲时任务策略说明
  • 也可以支持使用工作流模版替代数据处理指令。工作流模板是预先编排好的一系列媒体处理流程(如转码、截图、视频拼接等各类处理),登录 对象存储控制台 进行创建,详情参考工作流模板操作指南persistentWorkflowTemplateID 对应工作流模板列表的名称字段

    String accessKey = "access key";
    String secretKey = "secret key";
    String bucket = "bucket name";
    Auth auth = Auth.create(accessKey, secretKey);
    StringMap putPolicy = new StringMap();
    //工作流模版
    putPolicy.put("persistentWorkflowTemplateID", "tempname");
    //数据处理队列名称
    putPolicy.put("persistentPipeline", "mps-pipe1");
    //任务类型:0: 普通任务 1: 闲时任务,配置闲时任务时 persistentPipeline 不可配置
    putPolicy.put("persistentType", 1);
    //数据处理完成结果通知地址
    putPolicy.put("persistentNotifyUrl", "http://api.example.com/qiniu/pfop/notify");
    long expireSeconds = 3600;
    String upToken = auth.uploadToken(bucket, null, expireSeconds, putPolicy);
    System.out.println(upToken);
    
  • 需要注意的是,persistentWorkflowTemplateIDpersistentOps 两个参数只能二选一。
  • 带自定义参数的凭证

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

    putPolicy.put("returnBody", "{\"key\":\"$(key)\",\"hash\":\"$(etag)\",\"bucket\":\"$(bucket)\",\"fsize\":$(fsize),\"user\":\"$(x:user)\",\"age\",$(x:age)}");
    
    putPolicy.put("callbackBody", "{\"key\":\"$(key)\",\"hash\":\"$(etag)\",\"bucket\":\"$(bucket)\",\"fsize\":$(fsize),\"user\":\"$(x:user)\",\"age\",$(x:age)}");
    

    综合上传凭证

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

    上传凭证额外参数

    默认会拒绝不在预定义之中的参数。即:

    String upToken = auth.uploadToken(bucket, key, expireSeconds, putPolicy, true);
    

    若允许添加额外参数,可以将参数设置为false

    String upToken = auth.uploadToken(bucket, key, expireSeconds, putPolicy, false);
    

    服务端直传

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

    构建配置类

    存储支持空间创建在不同的机房,在使用 Java SDK 中的UploadManager上传文件之前,必须要构建一个上传用的Configuration对象,在该对象中,可以指定空间对应的Region以及其他的一些影响上传的参数。

    //构造一个带指定Region对象的配置类
    Configuration cfg = new Configuration(Region.region0());
    cfg.resumableUploadAPIVersion = Configuration.ResumableUploadAPIVersion.V2;// 指定分片上传版本
    //...其他参数参考类注释
    UploadManager uploadManager = new UploadManager(cfg);
    //...生成上传凭证,然后准备上传
    

    跨区域双活指定RegionGroup(内测功能,需要工单申请开通跨区域双活功能之后使用)

    Region region0 = Region.region0();
    Region region1 = Region.region1();
    RegionGroup regionGroup = new RegionGroup();
    regionGroup.addRegion(region0);
    regionGroup.addRegion(region1);
    Configuration config = new Configuration(regionGroup);
    config.resumableUploadAPIVersion = Configuration.ResumableUploadAPIVersion.V2;// 指定分片上传版本
    

    其中关于Region对象和机房的关系如下:

    Region
  • 若不指定 RegionRegion.autoRegion() ,则会使用 自动判断 区域,使用相应域名处理。
  • 如果可以明确 区域 的话,最好指定固定区域,这样可以少一步网络请求,少一步出错的可能。
  • 自定义区域域名

    Region region = new Region.Builder()
                    .region("z0")
                    .accUpHost("up.qiniup.com")
                    .srcUpHost("upload.qiniup.com")
                    .iovipHost("iovip.qiniuio.com")
                    .rsHost("rs.qiniu.com")
                    .rsfHost("rsf.qiniu.com")
                    .apiHost("api.qiniu.com")
                    .build();
    Configuration cfg = new Configuration(region);
    cfg.resumableUploadAPIVersion = Configuration.ResumableUploadAPIVersion.V2;// 指定分片上传版本
    

    设置请求协议为 http

    Configuration cfg = new Configuration(zone);
    cfg.resumableUploadAPIVersion = Configuration.ResumableUploadAPIVersion.V2;// 指定分片上传版本
    cfg.useHttpsDomains = false;
    UploadManager uploadManager = new UploadManager(cfg);
    

    最简单的就是上传本地文件,直接指定文件的完整路径即可上传。

    //构造一个带指定 Region 对象的配置类
    Configuration cfg = new Configuration(Region.region0());
    cfg.resumableUploadAPIVersion = Configuration.ResumableUploadAPIVersion.V2;// 指定分片上传版本
    //...其他参数参考类注释
    UploadManager uploadManager = new UploadManager(cfg);
    //...生成上传凭证,然后准备上传
    String accessKey = "your access key";
    String secretKey = "your secret key";
    String bucket = "your bucket name";
    //如果是Windows情况下,格式是 D:\\qiniu\\test.png
    String localFilePath = "/home/qiniu/test.png";
    //默认不指定key的情况下,以文件内容的hash值作为文件名
    String key = null;
    Auth auth = Auth.create(accessKey, secretKey);
    String upToken = auth.uploadToken(bucket);
    try {
        Response response = uploadManager.put(localFilePath, key, upToken);
        //解析上传成功的结果
        DefaultPutRet putRet = new Gson().fromJson(response.bodyString(), DefaultPutRet.class);
        System.out.println(putRet.key);
        System.out.println(putRet.hash);
    } catch (QiniuException ex) {
        ex.printStackTrace();
        if (ex.response != null) {
            System.err.println(ex.response);
            try {
                String body = ex.response.toString();
                System.err.println(body);
            } catch (Exception ignored) {
    

    字节数组上传

    可以支持将内存中的字节数组上传到空间中。

    //构造一个带指定 Region 对象的配置类
    Configuration cfg = new Configuration(Region.region0());
    cfg.resumableUploadAPIVersion = Configuration.ResumableUploadAPIVersion.V2;// 指定分片上传版本
    //...其他参数参考类注释
    UploadManager uploadManager = new UploadManager(cfg);
    //...生成上传凭证,然后准备上传
    String accessKey = "your access key";
    String secretKey = "your secret key";
    String bucket = "your bucket name";
    //默认不指定key的情况下,以文件内容的hash值作为文件名
    String key = null;
    try {
        byte[] uploadBytes = "hello qiniu cloud".getBytes("utf-8");
        Auth auth = Auth.create(accessKey, secretKey);
        String upToken = auth.uploadToken(bucket);
        try {
            Response response = uploadManager.put(uploadBytes, key, upToken);
            //解析上传成功的结果
            DefaultPutRet putRet = new Gson().fromJson(response.bodyString(), DefaultPutRet.class);
            System.out.println(putRet.key);
            System.out.println(putRet.hash);
        } catch (QiniuException ex) {
            ex.printStackTrace();
            if (ex.response != null) {
                System.err.println(ex.response);
                try {
                    String body = ex.response.toString();
                    System.err.println(body);
                } catch (Exception ignored) {
    } catch (UnsupportedEncodingException ex) {
        //ignore
    

    数据流上传

    这里演示的是InputStream对象的上传,适用于所有的InputStream子类。这里的ByteInputStream只用于演示目的,实际用法根据情况而定。

    //构造一个带指定 Region 对象的配置类
    Configuration cfg = new Configuration(Region.region0());
    cfg.resumableUploadAPIVersion = Configuration.ResumableUploadAPIVersion.V2;// 指定分片上传版本
    //...其他参数参考类注释
    UploadManager uploadManager = new UploadManager(cfg);
    //...生成上传凭证,然后准备上传
    String accessKey = "your access key";
    String secretKey = "your secret key";
    String bucket = "your bucket name";
    //默认不指定key的情况下,以文件内容的hash值作为文件名
    String key = null;
    try {
        byte[] uploadBytes = "hello qiniu cloud".getBytes("utf-8");
        ByteArrayInputStream byteInputStream=new ByteArrayInputStream(uploadBytes);
        Auth auth = Auth.create(accessKey, secretKey);
        String upToken = auth.uploadToken(bucket);
        try {
            Response response = uploadManager.put(byteInputStream,key,upToken,null, null);
            //解析上传成功的结果
            DefaultPutRet putRet = new Gson().fromJson(response.bodyString(), DefaultPutRet.class);
            System.out.println(putRet.key);
            System.out.println(putRet.hash);
        } catch (QiniuException ex) {
            ex.printStackTrace();
            if (ex.response != null) {
                System.err.println(ex.response);
                try {
                    String body = ex.response.toString();
                    System.err.println(body);
                } catch (Exception ignored) {
    } catch (UnsupportedEncodingException ex) {
        //ignore
    

    断点续上传

    断点续传是在分片上传的基础上实现。SDK 内置两种上传方式:表单上传和分片上传。表单上传使用一个 HTTP POST 请求完成文件的上传,因此比较适合较小的文件。相比而言,分片上传比较适合上传比较大的文件(例如数百 MB 或更大)。
    若需深入了解上传方式之间的区别,请参阅上传类型中 表单上传分片上传 v1 版分片上传 v2 版 接口说明。
    可以选择分片上传版本,推荐 Configuration.ResumableUploadAPIVersion.V2,表示 分片上传 v2 版,默认 Configuration.ResumableUploadAPIVersion.V1,表示 分片上传 v1 版。

    //构造一个带指定 Region 对象的配置类
    Configuration cfg = new Configuration(Region.region0());
    cfg.resumableUploadAPIVersion = Configuration.ResumableUploadAPIVersion.V2;// 指定分片上传版本
    cfg.resumableUploadMaxConcurrentTaskCount = 2;  // 设置分片上传并发,1:采用同步上传;大于1:采用并发上传
    //...其他参数参考类注释
    //...生成上传凭证,然后准备上传
    String accessKey = "your access key";
    String secretKey = "your secret key";
    String bucket = "your bucket name";
    //如果是Windows情况下,格式是 D:\\qiniu\\test.png
    String localFilePath = "/home/qiniu/test.mp4";
    //默认不指定key的情况下,以文件内容的hash值作为文件名
    String key = null;
    Auth auth = Auth.create(accessKey, secretKey);
    String upToken = auth.uploadToken(bucket);
    String localTempDir = Paths.get(System.getenv("java.io.tmpdir"), bucket).toString();
    try {
        //设置断点续传文件进度保存目录
        FileRecorder fileRecorder = new FileRecorder(localTempDir);
        UploadManager uploadManager = new UploadManager(cfg, fileRecorder);
        try {
            Response response = uploadManager.put(localFilePath, key, upToken);
            //解析上传成功的结果
            DefaultPutRet putRet = new Gson().fromJson(response.bodyString(), DefaultPutRet.class);
            System.out.println(putRet.key);
            System.out.println(putRet.hash);
        } catch (QiniuException ex) {
            ex.printStackTrace();
            if (ex.response != null) {
                System.err.println(ex.response);
                try {
                    String body = ex.response.toString();
                    System.err.println(body);
                } catch (Exception ignored) {
    } catch (IOException ex) {
        ex.printStackTrace();
    

    自定义参数上传

    //构造一个带指定 Region 对象的配置类
    Configuration cfg = new Configuration(Region.region0());
    cfg.resumableUploadAPIVersion = Configuration.ResumableUploadAPIVersion.V2;// 指定分片上传版本
    //...其他参数参考类注释
    //...生成上传凭证,然后准备上传
    String accessKey = "your access key";
    String secretKey = "your secret key";
    String bucket = "your bucket name";
    //如果是Windows情况下,格式是 D:\\qiniu\\test.png
    String localFilePath = "/home/qiniu/test.mp4";
    //默认不指定key的情况下,以文件内容的hash值作为文件名
    //设置上传后的文件名称
    String key = "qiniu_test.jpg";
    Auth auth = Auth.create(accessKey, secretKey);
    //上传自定义参数,自定义参数名称需要以 x:开头
    StringMap params = new StringMap();
    params.put("x:fname","123.jpg");
    params.put("x:age",20);
    //上传策略
    StringMap policy = new StringMap();
    //自定义上传后返回内容,返回自定义参数,需要设置 x:参数名称,注意下面
    policy.put("returnBody", "{\"key\":\"$(key)\",\"hash\":\"$(etag)\",\"fname\":\"$(x:fname)\",\"age\",$(x:age)}");
    //生成上传token
    String upToken = auth.uploadToken(bucket, key, 3600, policy);
    try {
        Response response = uploadManager.put(localFilePath, key, upToken,params,null,false);
        System.out.println(response.bodyString());
    } catch (QiniuException ex) {
        ex.printStackTrace();
        if (ex.response != null) {
            System.err.println(ex.response);
            try {
                String body = ex.response.toString();
                System.err.println(body);
            } catch (Exception ignored) {
    

    解析自定义回复内容

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

    遇到诸如自定义returnBody的情况:

    putPolicy.put("returnBody", "{\"key\":\"$(key)\",\"hash\":\"$(etag)\",\"bucket\":\"$(bucket)\",\"fsize\":$(fsize)}");
    

    或者是自定义了callbackBody的情况:

    putPolicy.put("callbackBody", "{\"key\":\"$(key)\",\"hash\":\"$(etag)\",\"bucket\":\"$(bucket)\",\"fsize\":$(fsize)}");
    

    我们只需要自己定义了对应的类,例如:

    class MyPutRet {
        public String key; // 文件保存的 key
        public String hash; // 文件保存的 Etag
        public String bucket; // 文件保存的 bucket
        public long fsize; // 文件的大小,单位:B
    

    然后在获取到上传回复的Response对象时,使用如下的方法就可以转为自定义回复的类对象了:

    MyPutRet myPutRet=response.jsonToObject(MyPutRet.class);
    

    业务服务器验证存储服务回调

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

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

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

    String accessKey = "your access key";
    String secretKey = "your secret key";
    * 这两个参数就是在定义PutPolicy参数时指定的内容
    //回调地址
    String callbackUrl = "http://api.example.com/qiniu/callback";
    //定义回调内容的组织格式,与上传策略中的callbackBodyType要保持一致
    //String callbackBodyType = "application/x-www-form-urlencoded"; //回调鉴权的签名包括请求内容callbackBody
    String callbackBodyType = "application/json";//回调鉴权的签名不包括请求内容
     * 这两个参数根据实际所使用的HTTP框架进行获取
    //通过获取请求的HTTP头部Authorization字段获得
    String callbackAuthHeader = "xxx";
    //通过读取回调POST请求体获得,不要设置为null
    byte[] callbackBody = null;
    Auth auth = Auth.create(accessKey, secretKey);
    //检查是否为合法的回调请求
    boolean validCallback = auth.isValidCallback(callbackAuthHeader, callbackUrl, callbackBody, callbackBodyType);
    if (validCallback) {
        //继续处理其他业务逻辑
    } else {
        //这是哪里的请求,被劫持,篡改了吧?
    

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

    手动拼接方式

    对于公开空间,其访问的链接主要是将空间绑定的域名拼接上空间里面的文件名即可访问,标准情况下需要在拼接链接之前,将文件名进行urlencode以兼容不同的字符。如果有其他访问处理需求,在文件名之后继续拼接即可。

    String fileName = "a/b/qiniu.jpg";
    // domainOfBucket 中的域名为用户 bucket 绑定的下载域名,下面域名仅为示例,不可使用
    String domainOfBucket = "http://mock.qiniu.com";
    String encodedFileName = URLEncoder.encode(fileName, "utf-8").replace("+", "%20");
    String finalUrl = String.format("%s/%s", domainOfBucket, encodedFileName);
    System.out.println(finalUrl);
    

    sdk 自动生成方式

    sdk 封装了下载 URL 的生成,只需要输入下载所需参数即可。已支持多媒体处理命令等。

    // domain   用户 bucket 绑定的下载域名 eg: mock.qiniu.com【必须】
    // useHttps 是否使用 https【必须】
    // key      下载资源在七牛云存储的 key【必须】
    DownloadUrl url = new DownloadUrl(domain, useHttps, key);
    url.setAttname(attname) // 配置 attname
       .setFop(fop) // 配置 fop
       .setStyle(style, styleSeparator, styleParam) // 配置 style
    String urlString = url.buildURL();
    System.out.println(urlString);
    

    手动拼接方式

    对于私有空间,首先需要按照公开空间的文件访问方式构建对应的公开空间访问链接,然后再对这个链接进行私有授权签名。

    String fileName = "公司/存储/qiniu.jpg";
    String domainOfBucket = "http://devtools.qiniu.com";
    String encodedFileName = URLEncoder.encode(fileName, "utf-8").replace("+", "%20");
    String publicUrl = String.format("%s/%s", domainOfBucket, encodedFileName);
    String accessKey = "your access key";
    String secretKey = "your secret key";
    Auth auth = Auth.create(accessKey, secretKey);
    long expireInSeconds = 3600;//1小时,可以自定义链接过期时间
    String finalUrl = auth.privateDownloadUrl(publicUrl, expireInSeconds);
    System.out.println(finalUrl);
    

    sdk 自动生成方式

    sdk 封装了下载 URL 的生成,只需要输入下载所需参数即可。已支持多媒体处理命令,过期时间 e 和 签名 token 等。

    // domain   下载 domain, eg: qiniu.com【必须】
    // useHttps 是否使用 https【必须】
    // key      下载资源在七牛云存储的 key【必须】
    DownloadUrl url = new DownloadUrl(domain, useHttps, key);
    url.setAttname(attname) // 配置 attname
       .setFop(fop) // 配置 fop
       .setStyle(style, styleSeparator, styleParam) // 配置 style
    // 带有效期
    long expireInSeconds = 3600;//1小时,可以自定义链接过期时间
    long deadline = System.currentTimeMillis()/1000 + expireInSeconds;
    Auth auth = Auth.create("your access key", "your secret key");
    String urlString = url.buildURL(auth, deadline);
    System.out.println(urlString);
    

    资源管理包括的主要功能有:

  • 获取文件信息
  • 修改文件类型
  • 移动或重命名文件
  • 复制文件副本
  • 删除空间中的文件
  • 设置或更新文件生存时间
  • 获取空间文件列表
  • 抓取网络资源到空间
  • 资源管理批量操作
  • 批量获取文件信息
  • 批量修改文件类型
  • 批量删除文件
  • 批量移动或重命名文件
  • 批量复制文件
  • 批量解冻归档存储类型文件
  • 批量混合指令操作
  • 更新镜像存储空间中的文件内容
  • 更新镜像存储空间中文件内容
  • 获取文件信息

    //构造一个带指定 Region 对象的配置类
    Configuration cfg = new Configuration(Region.region0());
    //...其他参数参考类注释
    String accessKey = "your access key";
    String secretKey = "your secret key";
    String bucket = "your bucket name";
    String key = "your file key";
    Auth auth = Auth.create(accessKey, secretKey);
    BucketManager bucketManager = new BucketManager(auth, cfg);
    try {
        FileInfo fileInfo = bucketManager.stat(bucket, key);
        System.out.println(fileInfo.hash);
        System.out.println(fileInfo.fsize);
        System.out.println(fileInfo.mimeType);
        System.out.println(fileInfo.putTime);
    } catch (QiniuException ex) {
        System.err.println(ex.response.toString());
    

    修改文件类型

    //构造一个带指定 Region 对象的配置类
    Configuration cfg = new Configuration(Region.region0());
    //...其他参数参考类注释
    String accessKey = "your access key";
    String secretKey = "your secret key";
    String bucket = "your bucket name";
    String key = "your file key";
    String newMimeType = "new mime type";
    Auth auth = Auth.create(accessKey, secretKey);
    BucketManager bucketManager = new BucketManager(auth, cfg);
    //修改文件类型
    try {
        bucketManager.changeMime(bucket, key, newMimeType);
    } catch (QiniuException ex) {
        System.out.println(ex.response.toString());
    

    移动或重命名文件

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

    目标文件名

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

    //构造一个带指定 Region 对象的配置类
    Configuration cfg = new Configuration(Region.region0());
    //...其他参数参考类注释
    String accessKey = "your access key";
    String secretKey = "your secret key";
    String fromBucket = "from bucket name";
    String fromKey = "from key";
    String toBucket = "to bucket name";
    String toKey = "to key";
    Auth auth = Auth.create(accessKey, secretKey);
    BucketManager bucketManager = new BucketManager(auth, cfg);
    try {
        bucketManager.move(fromBucket, fromKey, toBucket, toKey);
    } catch (QiniuException ex) {
        //如果遇到异常,说明移动失败
        System.err.println(ex.code());
        System.err.println(ex.response.toString());
    

    复制文件副本

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

    //构造一个带指定 Region 对象的配置类
    Configuration cfg = new Configuration(Region.region0());
    //...其他参数参考类注释
    String accessKey = "your access key";
    String secretKey = "your secret key";
    String fromBucket = "from bucket name";
    String fromKey = "from key";
    String toBucket = "to bucket name";
    String toKey = "to key";
    Auth auth = Auth.create(accessKey, secretKey);
    BucketManager bucketManager = new BucketManager(auth, cfg);
    try {
        bucketManager.copy(fromBucket, fromKey, toBucket, toKey);
    } catch (QiniuException ex) {
        //如果遇到异常,说明复制失败
        System.err.println(ex.code());
        System.err
    

    删除空间中的文件

    //构造一个带指定 Region 对象的配置类
    Configuration cfg = new Configuration(Region.region0());
    //...其他参数参考类注释
    String accessKey = "your access key";
    String secretKey = "your secret key";
    String bucket = "your bucket name";
    String key = "your file key";
    Auth auth = Auth.create(accessKey, secretKey);
    BucketManager bucketManager = new BucketManager(auth, cfg);
    try {
        bucketManager.delete(bucket, key);
    } catch (QiniuException ex) {
        //如果遇到异常,说明删除失败
        System.err.println(ex.code());
        System.err.println(ex.response.toString());
    

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

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

    //构造一个带指定 Region 对象的配置类
    Configuration cfg = new Configuration(Region.region0());
    //...其他参数参考类注释
    String accessKey = "access key";
    String secretKey = "secret key";
    String bucket = "bucket name";
    String key = "file key";
    //过期天数,该文件10天后删除
    int days = 10;
    Auth auth = Auth.create(accessKey, secretKey);
    BucketManager bucketManager = new BucketManager(auth, cfg);
    try {
        bucketManager.deleteAfterDays(bucket, key, days);
    } catch (QiniuException ex) {
        System.err.println(ex.response.toString());
    

    获取空间文件列表

    //构造一个带指定 Region 对象的配置类
    Configuration cfg = new Configuration(Region.region0());
    //...其他参数参考类注释
    String accessKey = "your access key";
    String secretKey = "your secret key";
    String bucket = "your bucket name";
    Auth auth = Auth.create(accessKey, secretKey);
    BucketManager bucketManager = new BucketManager(auth, cfg);
    //文件名前缀
    String prefix = "";
    //每次迭代的长度限制,最大1000,推荐值 1000
    int limit = 1000;
    //指定目录分隔符,列出所有公共前缀(模拟列出目录效果)。缺省值为空字符串
    String delimiter = "";
    //列举空间文件列表
    BucketManager.FileListIterator fileListIterator = bucketManager.createFileListIterator(bucket, prefix, limit, delimiter);
    while (fileListIterator.hasNext()) {
        //处理获取的file list结果
        FileInfo[] items = fileListIterator.next();
        for (FileInfo item : items) {
            System.out.println(item.key);
            System.out.println(item.hash);
            System.out.println(item.fsize);
            System.out.println(item.mimeType);
            System.out.println(item.putTime);
            System.out.println(item.endUser);
    

    抓取网络资源到空间

    //构造一个带指定 Region 对象的配置类
    Configuration cfg = new Configuration(Region.region0());
    //...其他参数参考类注释
    String accessKey = "your access key";
    String secretKey = "your secret key";
    String bucket = "your bucket name";
    String key = "your file key";
    String remoteSrcUrl = "http://devtools.qiniu.com/qiniu.png";
    Auth auth = Auth.create(accessKey, secretKey);
    BucketManager bucketManager = new BucketManager(auth, cfg);
    //抓取网络资源到空间
    try {
        FetchRet fetchRet = bucketManager.fetch(remoteSrcUrl, bucket, key);
        System.out.println(fetchRet.hash);
        System.out.println(fetchRet.key);
        System.out.println(fetchRet.mimeType);
        System.out.println(fetchRet.fsize);
    } catch (QiniuException ex) {
        System.err.println(ex.response.toString());
    

    资源管理批量操作

    批量获取文件信息

    //构造一个带指定 Region 对象的配置类
    Configuration cfg = new Configuration(Region.region0());
    //...其他参数参考类注释
    String accessKey = "your access key";
    String secretKey = "your secret key";
    String bucket = "your bucket name";
    Auth auth = Auth.create(accessKey, secretKey);
    BucketManager bucketManager = new BucketManager(auth, cfg);
    try {
        //单次批量请求的文件数量不得超过1000
        String[] keyList = new String[]{
                "qiniu.jpg",
                "qiniu.mp4",
                "qiniu.png",
        BucketManager.BatchOperations batchOperations = new BucketManager.BatchOperations();
        batchOperations.addStatOps(bucket, keyList);
        Response response = bucketManager.batch(batchOperations);
        BatchStatus[] batchStatusList = response.jsonToObject(BatchStatus[].class);
        for (int i = 0; i < keyList.length; i++) {
            BatchStatus status = batchStatusList[i];
            String key = keyList[i];
            System.out.print(key+"\t");
            if (status.code == 200) {
                //文件存在
                System.out.println(status.data.hash);
                System.out.println(status.data.mimeType);
                System.out.println(status.data.fsize);
                System.out.println(status.data.putTime);
            } else {
                System.out.println(status.data.error);
    } catch (QiniuException ex) {
        System.err.println(ex.response.toString());
    

    批量修改文件类型

    //构造一个带指定 Region 对象的配置类
    Configuration cfg = new Configuration(Region.region0());
    //...其他参数参考类注释
    String accessKey = "your access key";
    String secretKey = "your secret key";
    String bucket = "your bucket name";
    Auth auth = Auth.create(accessKey, secretKey);
    BucketManager bucketManager = new BucketManager(auth, cfg);
    try {
        //单次批量请求的文件数量不得超过1000
        HashMap<String, String> keyMimeMap = new HashMap<>();
        keyMimeMap.put("qiniu.jpg", "image/jpg");
        keyMimeMap.put("qiniu.png", "image/png");
        keyMimeMap.put("qiniu.mp4", "video/mp4");
        BucketManager.BatchOperations batchOperations = new BucketManager.BatchOperations();
        //添加指令
        for (Map.Entry<String, String> entry : keyMimeMap.entrySet()) {
            String key = entry.getKey();
            String newMimeType = entry.getValue();
            batchOperations.addChgmOp(bucket, key, newMimeType);
        Response response = bucketManager.batch(batchOperations);
        BatchStatus[] batchStatusList = response.jsonToObject(BatchStatus[].class);
        int index = 0;
        for (Map.Entry<String, String> entry : keyMimeMap.entrySet()) {
            String key = entry.getKey();
            System.out.print(key + "\t");
            BatchStatus status = batchStatusList[index];
            if (status.code == 200) {
                System.out.println("change mime success");
            } else {
                System.out.println(status.data.error);
            index += 1;
    } catch (QiniuException ex) {
        System.err.println(ex.response.toString());
    

    批量删除文件

    //构造一个带指定 Region 对象的配置类
    Configuration cfg = new Configuration(Region.region0());
    //...其他参数参考类注释
    String accessKey = "your access key";
    String secretKey = "your secret key";
    String bucket = "your bucket name";
    Auth auth = Auth.create(accessKey, secretKey);
    BucketManager bucketManager = new BucketManager(auth, cfg);
    try {
        //单次批量请求的文件数量不得超过1000
        String[] keyList = new String[]{
                "qiniu.jpg",
                "qiniu.mp4",
                "qiniu.png",
        BucketManager.BatchOperations batchOperations = new BucketManager.BatchOperations();
        batchOperations.addDeleteOp(bucket, keyList);
        Response response = bucketManager.batch(batchOperations);
        BatchStatus[] batchStatusList = response.jsonToObject(BatchStatus[].class);
        for (int i = 0; i < keyList.length; i++) {
            BatchStatus status = batchStatusList[i];
            String key = keyList[i];
            System.out.print(key + "\t");
            if (status.code == 200) {
                System.out.println("delete success");
            } else {
                System.out.println(status.data.error);
    } catch (QiniuException ex) {
        System.err.println(ex.response.toString());
    

    批量移动或重命名文件

    Configuration cfg = new Configuration(Region.region0()); //...其他参数参考类注释 String accessKey = "your access key"; String secretKey = "your secret key"; String bucket = "your bucket name"; Auth auth = Auth.create(accessKey, secretKey); BucketManager bucketManager = new BucketManager(auth, cfg); try { //单次批量请求的文件数量不得超过1000 String[] keyList = new String[]{ "qiniu.jpg", "qiniu.mp4", "qiniu.png", BucketManager.BatchOperations batchOperations = new BucketManager.BatchOperations(); for (String key : keyList) { batchOperations.addMoveOp(bucket, key, bucket, key + "_move"); Response response = bucketManager.batch(batchOperations); BatchStatus[] batchStatusList = response.jsonToObject(BatchStatus[].class); for (int i = 0; i < keyList.length; i++) { BatchStatus status = batchStatusList[i]; String key = keyList[i]; System.out.print(key + "\t"); if (status.code == 200) { System.out.println("move success"); } else { System.out.println(status.data.error); } catch (QiniuException ex) { System.err.println(ex.response.toString());

    批量复制文件

    Configuration cfg = new Configuration(Region.region0()); //...其他参数参考类注释 String accessKey = "your access key"; String secretKey = "your secret key"; String bucket = "your bucket name"; Auth auth = Auth.create(accessKey, secretKey); BucketManager bucketManager = new BucketManager(auth, cfg); try { //单次批量请求的文件数量不得超过1000 String[] keyList = new String[]{ "qiniu.jpg", "qiniu.mp4", "qiniu.png", BucketManager.BatchOperations batchOperations = new BucketManager.BatchOperations(); for (String key : keyList) { batchOperations.addCopyOp(bucket, key, bucket, key + "_copy"); Response response = bucketManager.batch(batchOperations); BatchStatus[] batchStatusList = response.jsonToObject(BatchStatus[].class); for (int i = 0; i < keyList.length; i++) { BatchStatus status = batchStatusList[i]; String key = keyList[i]; System.out.print(key + "\t"); if (status.code == 200) { System.out.println("copy success"); } else { System.out.println(status.data.error); } catch (QiniuException ex) { System.err.println(ex.response.toString());

    批量解冻归档存储类型文件

    Configuration cfg = new Configuration(Region.region0()); //...其他参数参考类注释 String accessKey = "your access key"; String secretKey = "your secret key"; String bucket = "your bucket name"; Auth auth = Auth.create(accessKey, secretKey); BucketManager bucketManager = new BucketManager(auth, cfg); try { //单次批量请求的文件数量不得超过1000 String[] keyList = new String[]{ "qiniu.jpg", "qiniu.mp4", "qiniu.png", int freezeAfterDays = 7 ; BucketManager.BatchOperations batchOperations = new BucketManager.BatchOperations(); for (String key : keyList) { batchOperations.addRestoreArchiveOps(bucket, freezeAfterDays, key); Response response = bucketManager.batch(batchOperations); BatchStatus[] batchStatusList = response.jsonToObject(BatchStatus[].class); for (int i = 0; i < keyList.length; i++) { BatchStatus status = batchStatusList[i]; String key = keyList[i]; System.out.print(key + "\t"); if (status.code == 200) { System.out.println("restoreAr success"); } else { System.out.println(status.data.error); } catch (QiniuException ex) { System.err.println(ex.response.toString());

    批量混合指令操作

    其实batch接口支持混合指令的处理,不过为了方便解析请求的回复,一般不推荐这样做。

    Configuration cfg = new Configuration(Region.region0()); //...其他参数参考类注释 String accessKey = "your access key"; String secretKey = "your secret key"; String bucket = "your bucket name"; Auth auth = Auth.create(accessKey, secretKey); BucketManager bucketManager = new BucketManager(auth, cfg); try { //单次批量请求的文件数量不得超过1000 BucketManager.BatchOperations batchOperations = new BucketManager.BatchOperations(); //添加混合指令 batchOperations.addStatOps(bucket, "qiniu.png", "qiniu.jpg"); batchOperations.addCopyOp(bucket, "qiniu.png", bucket, "qiniu_copy1.png"); batchOperations.addMoveOp(bucket, "qiniu2.png", bucket, "qiniu3.png"); batchOperations.addDeleteOp(bucket, "qiniu4.png"); batchOperations.addRestoreArchiveOps(bucket, 1, "qiniu.png"); Response response = bucketManager.batch(batchOperations); BatchStatus[] batchStatusList = response.jsonToObject(BatchStatus[].class); for (BatchStatus status : batchStatusList) { if (status.code == 200) { System.out.println("operation success"); } else { System.out.println(status.data.error); } catch (QiniuException ex) { System.err.println(ex.response.toString());

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

    对于配置了镜像存储的空间,如果镜像源站更新了文件内容,则默认情况下,七牛不会再主动从客户镜像源站同步新的副本,这个时候就需要利用这个prefetch接口来主动地将空间中的文件和更新后的源站副本进行同步。调用方式很简单,指定空间和文件名即可。

    //构造一个带指定 Region 对象的配置类
    Configuration cfg = new Configuration(Region.region0());
    //...其他参数参考类注释
    String accessKey = "your access key";
    String secretKey = "your secret key";
    String bucket = "your bucket name";
    String key = "your file key";
    Auth auth = Auth.create(accessKey, secretKey);
    BucketManager bucketManager = new BucketManager(auth, cfg);
    try {
        bucketManager.prefetch(bucket, key);
    } catch (QiniuException ex) {
        //如果遇到异常,说明更新失败
        System.err.println(ex.code());
        System.err.println(ex.response.toString());
    

    持久化数据处理

    发送数据处理请求(数据处理指令)

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

    闲时任务的功能介绍、使用场景、定价,详见 闲时任务策略说明

    String accessKey = "access key";
    String secretKey = "secret key";
    //待处理文件所在空间
    String bucket = "bucket name";
    //待处理文件名
    String key = "file key";
    Auth auth = Auth.create(accessKey, secretKey);
    //数据处理指令,支持多个指令
    String saveMp4Entry = String.format("%s:avthumb_test_target.mp4", bucket);
    String saveJpgEntry = String.format("%s:vframe_test_target.jpg", bucket);
    String avthumbMp4Fop = String.format("avthumb/mp4|saveas/%s", UrlSafeBase64.encodeToString(saveMp4Entry));
    String vframeJpgFop = String.format("vframe/jpg/offset/1|saveas/%s", UrlSafeBase64.encodeToString(saveJpgEntry));
    //将多个数据处理指令拼接起来
    String persistentOpfs = StringUtils.join(new String[]{
            avthumbMp4Fop, vframeJpgFop
    }, ";");
    //数据处理队列名称,必须
    String persistentPipeline = "mps-pipe1";
    //任务类型:0: 普通任务 1: 闲时任务,配置闲时任务时 persistentPipeline 不可配置(指定为 null)
    Integer persistentType = 1;
    //数据处理完成结果通知地址
    String persistentNotifyUrl = "http://api.example.com/qiniu/pfop/notify";
    //构造一个带指定 Region 对象的配置类
    Configuration cfg = new Configuration(Region.region0());
    //...其他参数参考类注释
    //构建持久化数据处理对象
    OperationManager operationManager = new OperationManager(auth, cfg);
    try {
        String persistentId = operationManager.pfop(bucket, key, persistentOpfs, persistentPipeline, persistentNotifyUrl, persistentType, true);
        //可以根据该 persistentId 查询任务处理进度
        System.out.println(persistentId);
        OperationStatus operationStatus = operationManager.prefop(persistentId);
        //解析 operationStatus 的结果
    } catch (QiniuException e) {
        System.err.println(e.response.toString());
    

    发送数据处理请求(工作流模版)

    也可以支持使用工作流模版替代数据处理指令。工作流模板是预先编排好的一系列媒体处理流程(如转码、截图、视频拼接等各类处理),登录 对象存储控制台 进行创建,详情参考工作流模板操作指南persistentWorkflowTemplateID 对应工作流模板列表的名称字段

    String accessKey = "access key";
    String secretKey = "secret key";
    //待处理文件所在空间
    String bucket = "bucket name";
    //待处理文件名
    String key = "file key";
    Auth auth = Auth.create(accessKey, secretKey);
    //工作流模版,必须
    String persistentWorkflowTemplateID = "tempname";
    //数据处理队列名称,必须
    String persistentPipeline = "mps-pipe1";
    //任务类型:0: 普通任务 1: 闲时任务,配置闲时任务时 persistentPipeline 不可配置(指定为 null)
    Integer persistentType = 1;
    //数据处理完成结果通知地址
    String persistentNotifyUrl = "http://api.example.com/qiniu/pfop/notify";
    //构造一个带指定 Region 对象的配置类
    Configuration cfg = new Configuration(Region.region0());
    //...其他参数参考类注释
    //构建持久化数据处理对象
    OperationManager operationManager = new OperationManager(auth, cfg);
    try {
        StringMap params = new StringMap().
            putNotEmpty("persistentWorkflowTemplateID", persistentWorkflowTemplateID).
            putNotEmpty("pipeline", persistentPipeline).
            putNotEmpty("notifyURL", persistentNotifyUrl).
            putNotNull("type", persistentType);
        String persistentId = operationManager.pfop(bucket, key, params);
        //可以根据该 persistentId 查询任务处理进度
        System.out.println(persistentId);
        OperationStatus operationStatus = operationManager.prefop(persistentId);
        //解析 operationStatus 的结果
    } catch (QiniuException e) {
        System.err.println(e.response.toString());
    

    查询数据处理请求状态

    由于数据处理是异步处理,可以根据发送处理请求时返回的 persistentId 去查询任务的处理进度,如果在设置了persistentNotifyUrl 的情况下,直接业务服务器等待处理结果通知即可,如果需要主动查询,可以采用如上代码中的:

    OperationStatus operationStatus = operationManager.prefop(persistentId);
    //解析 operationStatus 的结果
    

    CDN 相关功能

  • 文件预取操作
  • 获取域名流量
  • 获取域名带宽
  • 获取日志下载链接
  • 构建时间戳防盗链访问链接
  • String accessKey = "your access key";
    String secretKey = "your secret key";
    Auth auth = Auth.create(accessKey, secretKey);
    CdnManager c = new CdnManager(auth);
    //待刷新的链接列表
    String[] urls = new String[]{
            "http://javasdk.qiniudn.com/gopher1.jpg",
            "http://javasdk.qiniudn.com/gopher2.jpg",
            //....
    try {
        //单次方法调用刷新的链接不可以超过100个
        CdnResult.RefreshResult result = c.refreshUrls(urls);
        System.out.println(result.code);
        //获取其他的回复内容
    } catch (QiniuException e) {
        System.err.println(e.response.toString());
    
    String accessKey = "your access key";
    String secretKey = "your secret key";
    Auth auth = Auth.create(accessKey, secretKey);
    CdnManager c = new CdnManager(auth);
    //待刷新的目录列表,目录必须以 / 结尾
    String[] dirs = new String[]{
            "http://javasdk.qiniudn.com/gopher1/",
            "http://javasdk.qiniudn.com/gopher2/",
            //....
    try {
        //单次方法调用刷新的目录不可以超过10个,另外刷新目录权限需要联系技术支持开通
        CdnResult.RefreshResult result = c.refreshDirs(dirs);
        System.out.println(result.code);
        //获取其他的回复内容
    } catch (QiniuException e) {
        System.err.println(e.response.toString());
    
    public static void getRefreshResult() {
    	String accessKey = "";
    	String secretKey = "";
    	String url ="http://fusion.qiniuapi.com/v2/tune/refresh/list";
    	String body = "{\"urls\":[\"http://p9w3dsbag.bkt.clouddn.com/demo.html\"]}";
    	Auth auth = Auth.create(accessKey, secretKey);
    	StringMap str = auth.authorization(url, body.getBytes(), Client.JsonMime);
    	Client client = new Client();
    	try {
    		Response r = client.post(url, body.getBytes(), str);
    		System.out.println(r.reqId);
    		System.out.println(r.bodyString());
    	} catch (QiniuException e) {
    		// TODO Auto-generated catch block
    		e.printStackTrace();
    
    String accessKey = "your access key";
    String secretKey = "your secret key";
    Auth auth = Auth.create(accessKey, secretKey);
    CdnManager c = new CdnManager(auth);
    //待预取的文件链接
    String[] urls = new String[]{
            "http://javasdk.qiniudn.com/gopher1.jpg",
            "http://javasdk.qiniudn.com/gopher2.jpg",
            //...
    try {
        //单次调用方法预取的链接数量不得超过100个
        CdnResult.PrefetchResult result = c.prefetchUrls(urls);
        System.out.println(result.code);
        //获取其他的回复内容
    } catch (QiniuException e) {
        System.err.println(e.response.toString());
    

    获取域名流量

    String accessKey = "your access key";
    String secretKey = "your secret key";
    Auth auth = Auth.create(accessKey, secretKey);
    CdnManager c = new CdnManager(auth);
    //域名列表
    String[] domains = new String[]{
            "img1.example.com",
            "img2.example.com",
    //开始和结束日期
    String fromDate = "2017-01-02";
    String toDate = "2017-01-10";
    //数据粒度,支持的取值为 5min / hour /day
    String granularity = "day";
    try {
        CdnResult.FluxResult fluxResult = c.getFluxData(domains, fromDate, toDate, granularity);
        //处理得到的结果数据
        //...
    } catch (QiniuException e) {
        System.err.println(e.response.toString());
    

    获取域名带宽

    String accessKey = "your access key";
    String secretKey = "your secret key";
    Auth auth = Auth.create(accessKey, secretKey);
    CdnManager c = new CdnManager(auth);
    //域名列表
    String[] domains = new String[]{
            "img1.example.com",
            "img2.example.com",
    //开始和结束日期
    String fromDate = "2017-01-02";
    String toDate = "2017-01-10";
    //数据粒度,支持的取值为 5min / hour /day
    String granularity = "day";
    try {
        CdnResult.BandwidthResult bandwidthResult = c.getBandwidthData(domains, fromDate, toDate, granularity);
        //处理得到的结果数据
        //...
    } catch (QiniuException e) {
        System.err.println(e.response.toString());
    

    获取日志下载链接

    String accessKey = "your access key";
    String secretKey = "your secret key";
    Auth auth = Auth.create(accessKey, secretKey);
    CdnManager c = new CdnManager(auth);
    //域名列表
    String[] domains = new String[]{
            "img1.example.com",
            "img2.example.com",
    //具体日期
    String logDate = "2017-01-02";
    try {
        CdnResult.LogListResult logListResult = c.getCdnLogList(domains, logDate);
        //处理得到的结果数据
        //...
    } catch (QiniuException e) {
        System.err.println(e.response.toString());
    

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

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

    String host = "http://video.example.com";
    String fileName = "基本概括.mp4";
    //查询参数
    StringMap queryStringMap = new StringMap();
    queryStringMap.put("name", "七牛");
    queryStringMap.put("year", 2017);
    queryStringMap.put("年龄", 28);
    //链接过期时间
    long deadline = System.currentTimeMillis() / 1000 + 3600;
    //签名密钥,从后台域名属性中获取
    String encryptKey = "xxx";
    String signedUrl;
    try {
        signedUrl = CdnManager.createTimestampAntiLeechUrl(host, fileName,
                queryStringMap, encryptKey, deadline);
        System.out.println(signedUrl);
    } catch (Exception ex) {
        ex.printStackTrace();
    

    API 参考

  • 存储 API 参考
  • 融合 CDN API 参考
  • 官方数据处理 API 参考
  • 视频监控 QVS API 参考
  • QiniuExeption 保留了请求响应的信息,失败情况下会抛出此异常,可以提交给我们排查问题。
  • API 的使用,demo 可以参考单元测试
  • 如果您有任何关于我们文档或产品的建议和想法,欢迎您通过以下方式与我们互动讨论:

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

    提交您的改动 git commit -am ‘Added some feature’

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

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

    基于 MIT 协议发布:

  • www.opensource.org/licenses/MIT
  •