human: 如何处理七牛云的智能多媒体服务处理结果另存（saveas）

gpt: [智能多媒体服务](https://developer.qiniu.com/dora) > API 文档 > 数据处理机制 >处理结果另存（saveas）

#  处理结果另存（saveas）

最近更新时间: 2024-08-13 10:19:56

# **简介**

我们提供名为`saveas` 的数据处理接口，将处理结果作为资源保存到指定空间内，并赋以指定 Key。保存成功后，下一次可直接通过指定 Key
来访问该资源，以达到提升下载速度的效果。

## **限制说明**

  * `处理结果不能跨区域另存`，源Bucket和目标Bucket必须在同一区域，例如华东Bucket内的文件经处理后结果无法另存到华北的Bucket。

  * 支持 `同步调用` 和 `持久化(pfop)调用` ，两者调用方式有轻微的差异。大多数使用场景下，建议使用 [持久化处理 __](https://developer.qiniu.com/dora/1291/persistent-data-processing-pfop)来实现处理结果存储，避免使用同步操作的 saveas 接口，提升访问速度。

    * **注意** ：当持久化处理(pfop)调用，不用 `saveas` 接口时，系统会默认生成输出结果文件，输出空间默认跟随源文件，结果文件命名根据源文件hash和处理命令生成一个唯一标识的文件名。
  * urlsafe_base64_encode() 函数按照标准的RFC 4648实现，开发者可以参考github.com/qiniu上各 SDK 的样例代码。

  * 当持久化保存的 fop 耗时较长的时候，saveas 请求会返回 CDN 超时，但是只要保证发送的 saveas 请求合法，七牛服务器还是会对请求做正确处理。

  * 此处签名内容不包含 Scheme 部分，与 DownloadToken 签名不一样。

  * c# http 库发送请求的时候会把 | 转成 %7c，由于签名签的是 | ，导致报 400 错误。可以在发送请求的时候，把 url 中的 | 改为 %7c，或者签名的时候签 %7c。

# **接口规格**

    
    
    saveas/<EncodedEntryURI>/deleteAfterDays/<deleteAfterDays>/sign/<Sign>/savekey/<savekey>
    

参数名称 | 必填 | 类型 | 说明  
---|---|---|---  
` <EncodedEntryURI>` | 是 | string | 以 [EncodedEntryURI __](https://developer.qiniu.com/kodo/api/1276/data-format)格式组织的目标 Bucket 与 Key。  
**注意** ：  
key 和 saveKey 二选一，不能同时指定。  
` <deleteAfterDays>` | 否 | int | 最小单位为天，数值 >= 1。表示从保存数据开始算起多少天之后自动从 bucket 删除文件。不设置表示资源不会被自动删除  
`<Sign>` | 是 | string | `同步调用` 需要签名，签名算法见同步调用示例；  
`持久化(pfop)调用 `，不用指定该参数。  
`saveKey` | 否 | string | 自定义输出文件资源名。  
可使用 `文件名变量`，变量值都是基于输出文件获取，包括：`etag, year, mon, day, hour, min, sec`，均需要经过
`urlsafe_base64_encode`，变量引用格式为 ${var}、$(var)。  
**注意** ：  
saveKey 仅当` <EncodedEntryURI>`没有指定 key 时起作用，不能和key 同时指定。  
  
# **文件名变量**

文件名变量是一组预先定义的变量，可以使用 `$(变量名)`或`${变量名}` 形式求值。目前可用的变量如下:

变量名 | 变量说明  
---|---  
etag | 文件上传成功后的 HTTP[ETag __](https://developer.qiniu.com/kodo/glossary/1649/e#etag)。若上传时未指定资源ID，Etag将作为资源ID使用。  
year | 上传时的年份。  
mon | 上传时的月份。  
day | 上传时的日期。  
hour | 上传时的小时。  
min | 上传时的分钟。  
sec | 上传时的秒钟。  
  
## **求值示例**

输入文件上传原始文件名=demo.mp4

输入文件空间资源名= file.mp4

输出文件上传日期=2024.06.05 12:30:50

输出文件etag=FukjnhlamMYsy-SvkpxsDzQBP0_9

`saveKey` 填写如下文件名变量，输出结果文件会是：

>   * saveKey=file${year}${.mon}${day}${hour}${min}.m3u8，
> 结果文件为=file202406051230.m3u8
>   * saveKey=${etag}.m3u8， 结果文件为=FukjnhlamMYsy-SvkpxsDzQBP0_9.m3u8
>

# **持久化处理(pfop)调用示例**

在 [持久化处理(pfop)__](https://developer.qiniu.com/dora/1291/persistent-data-
processing-pfop)调用中，在处理命令后加上`|saveas/SafeBase64(bucket:key)/deleteAfterDays/<
deleteAfterDays >` ，指定的 Bucket 与 Key 来保存处理结果。

比如：将上传的视频文件转码`flv`格式后存储为`qbucket:qkey`，在 3 天之后会从 bucket
自动删除，其中`cWJ1Y2tldDpxa2V5 `是 `qbucket:qkey` 的 [URL安全的Base64编码
__](https://developer.qiniu.com/kodo/manual/1231/appendix#urlsafe-base64)结果。

  * 上传时自动触发，设置 `persistentOps` 字段
    
        "persistentOps":"avthumb/flv|saveas/cWJ1Y2tldDpxa2V5/deleteAfterDays/3"
    

  * 已有资源主动触发，设置`fops`字段
    
        "fops":"avthumb/flv|saveas/cWJ1Y2tldDpxa2V5/deleteAfterDays/3"
    

# **同步调用示例**

**1.签名算法如下：**

a. 在下载 URL（不含 Scheme 部分，即去除 http : //）后附加 saveas 接口（不含签名部分）：

    
    
    NewURL = URL + "|saveas/<EncodedEntryURI>"
    

b. 使用 SecretKey 对新的下载 URL 进行HMAC1-SHA1签名：

    
    
    Sign = hmac_sha1(SecretKey, NewURL)
    

c. 对签名进行URL安全的Base64编码：

    
    
    EncodedSign = urlsafe_base64_encode(Sign)
    

d. 在新的下载 URL 后拼接签名参数：

    
    
    FinalURL = NewURL + "/sign/<AccessKey>:<EncodedSign>"
    

**2\. 同步调用 saveas 算法示例，生成 saveas 请求的完整 Go 代码如下：**

    
    
    func makeSaveasUrl(URL, accessKey string, secretKey []byte, saveBucket, saveKey string) string {
          encodedEntryURI := base64.URLEncoding.EncodeToString([]byte(saveBucket+":"+saveKey))
          URL += "|saveas/" + encodedEntryURI
          h := hmac.New(sha1.New, secretKey)
          // 签名内容不包括Scheme，仅含如下部分：
        // <Domain>/<Path>?<Query>
          u, _ := url.Parse(URL)
          io.WriteString(h, u.Host + u.RequestURI())
          d := h.Sum(nil)
          sign := accessKey + ":" + base64.URLEncoding.EncodeToString(d)
          return URL + "/sign/" + sign
    }
    

**3.同步调用示例**

a. 原资源是一个名为 resource/Ship.jpg 的图片：

    
    
    http://78re52.com1.z0.glb.clouddn.com/resource/Ship.jpg
    

b. 将图片做缩略处理：

    
    
    http://78re52.com1.z0.glb.clouddn.com/resource/Ship.jpg?imageView2/2/w/200/h/200
    

c.对上述云处理结果进行持久化保存：

    
    
    # 另存操作的目标空间与资源名
    entryURI = "qiniu-developer:Ship-thumb-200.jpg"
    #编码结果
    encodedEntryURI = "cWluaXUtZGV2ZWxvcGVyOlNoaXAtdGh1bWItMjAwLmpwZw=="
    #需要签名的部分
    signingStr = "78re52.com1.z0.glb.clouddn.com/resource/Ship.jpg?imageView2/2/w/200/h/200|saveas/cWluaXUtZGV2ZWxvcGVyOlNoaXAtdGh1bWItMjAwLmpwZw=="
    #签名结果
    sign = "bcgojLbLKTsTlhm3XFMYq0cn3lW2G3NAuJYXZDDf:jGo09Pmq5vyG4c-rRb4qF3_dH1g="
    

d. 最终得到的完整下载 URL：

    
    
    http://78re52.com1.z0.glb.clouddn.com/resource/Ship.jpg?imageView2/2/w/200/h/200|saveas/cWluaXUtZGV2ZWxvcGVyOlNoaXAtdGh1bWItMjAwLmpwZw==/sign/bcgojLbLKTsTlhm3XFMYq0cn3lW2G3NAuJYXZDDf:jGo09Pmq5vyG4c-rRb4qF3_dH1g=
    

e.保存转码后资源可通过如下 URL 访问：

    
    
    http://78re52.com1.z0.glb.clouddn.com/Ship-thumb-200.jpg
    

# **EncodedEntryURI 格式**

本格式用于在 URI中指定目标资源空间与目标资源名，格式如下：

    
    
    entry = '<Bucket>:<Key>'
    encodedEntryURI = urlsafe_base64_encode(entry)
    

假设 **entry** 为 `qiniuphotos:gogopher.jpg` ，则对应的 **encodedEntryURI** 为
`cWluaXVwaG90b3M6Z29nb3BoZXIuanBn=` 。

## URL安全的Base64编码

URL安全的Base64编码适用于以URL方式传递Base64编码结果的场景。该编码方式的基本过程是先将内容以Base64格式编码为字符串，然后检查该结果字符串，将字符串中的加号`+`换成中划线`-`，并且将斜杠`/`换成下划线`_`。

以上内容是否对您有帮助？