对象存储OSS的图片处理服务默认不保存处理后的图片,您需要在图片处理的请求内添加转存参数,将处理后的图片作为文件(Object)保存至指定的存储空间(Bucket)内。

注意事项

  • 权限要求

    进行图片转存操作要求具有源Bucket的oss:PostProcessTask权限,以及目标Bucket的oss:PutBucket和目标Object的oss:PutObject权限。

  • 存储地域

    原图所在Bucket和处理后图片转存的目标Bucket可以相同也可以不同,但必须属于同一账号下的相同地域。

  • 转存方式
    • 支持通过添加转存参数的方式将阿里云SDK处理后的图片保存至指定Bucket。具体操作,请参见阿里云SDK图片处理持久化示例
    • 不支持将文件URL处理后的图片直接转存至指定Bucket。您可以将处理后的图片保存到本地,然后再上传至指定Bucket。
  • 转存图片读写权限ACL

    转存图片的读写权限ACL默认继承Bucket,不支持自定义。

  • 转存图片存储时长

    如果您需要调整转存图片的存储时长,请结合生命周期规则配置合理的文件过期策略。

使用阿里云SDK

以下仅列举常见SDK的图片处理持久化的代码示例。关于其他SDK的图片处理持久化的代码示例,请参见SDK简介

import com.aliyun.oss.*;
import com.aliyun.oss.common.utils.BinaryUtil;
import com.aliyun.oss.common.utils.IOUtils;
import com.aliyun.oss.model.GenericResult;
import com.aliyun.oss.model.ProcessObjectRequest;
import java.util.Formatter;

public class Demo {
    public static void main(String[] args) throws Throwable {
        // Endpoint以华东1(杭州)为例,其它Region请按实际情况填写。
        String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
        // 阿里云账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM用户进行API访问或日常运维,请登录RAM控制台创建RAM用户。
        String accessKeyId = "yourAccessKeyId";
        String accessKeySecret = "yourAccessKeySecret";
        // 填写Bucket名称,例如examplebucket。
        String bucketName = "examplebucket";
        // 填写Object完整路径。Object完整路径中不能包含Bucket名称。
        String sourceImage = "exampleimage.png";

        // 创建OSSClient实例。
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);

        try {
            // 将图片缩放为固定宽高100 px。
            StringBuilder sbStyle = new StringBuilder();
            Formatter styleFormatter = new Formatter(sbStyle);
            String styleType = "image/resize,m_fixed,w_100,h_100";
            // 将处理后的图片命名为example-resize.png并保存到当前Bucket。
            // 填写Object完整路径。Object完整路径中不能包含Bucket名称。
            String targetImage = "example-resize.png";
            styleFormatter.format("%s|sys/saveas,o_%s,b_%s", styleType,
                    BinaryUtil.toBase64String(targetImage.getBytes()),
                    BinaryUtil.toBase64String(bucketName.getBytes()));
            System.out.println(sbStyle.toString());
            ProcessObjectRequest request = new ProcessObjectRequest(bucketName, sourceImage, sbStyle.toString());
            GenericResult processResult = ossClient.processObject(request);
            String json = IOUtils.readStreamAsString(processResult.getResponse().getContent(), "UTF-8");
            processResult.getResponse().getContent().close();
            System.out.println(json);
        } catch (OSSException oe) {
            System.out.println("Caught an OSSException, which means your request made it to OSS, "
                    + "but was rejected with an error response for some reason.");
            System.out.println("Error Message:" + oe.getErrorMessage());
            System.out.println("Error Code:" + oe.getErrorCode());
            System.out.println("Request ID:" + oe.getRequestId());
            System.out.println("Host ID:" + oe.getHostId());
        } catch (ClientException ce) {
            System.out.println("Caught an ClientException, which means the client encountered "
                    + "a serious internal problem while trying to communicate with OSS, "
                    + "such as not being able to access the network.");
            System.out.println("Error Message:" + ce.getMessage());
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
    }
}
<?php
if (is_file(__DIR__ . '/../autoload.php')) {
    require_once __DIR__ . '/../autoload.php';
}
if (is_file(__DIR__ . '/../vendor/autoload.php')) {
    require_once __DIR__ . '/../vendor/autoload.php';
}

use OSS\OssClient;

// 阿里云账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM用户进行API访问或日常运维,请登录RAM控制台创建RAM用户。
$accessKeyId = "yourAccessKeyId";
$accessKeySecret = "yourAccessKeySecret";
// yourEndpoint填写Bucket所在地域对应的Endpoint。以华东1(杭州)为例,Endpoint填写为https://oss-cn-hangzhou.aliyuncs.com。
$endpoint = "yourEndpoint";
// 填写Bucket名称,例如examplebucket。
$bucket= "examplebucket";
// 填写源Object完整路径,例如exampledir/exampleobject.jpg。Object完整路径中不能包含Bucket名称。
$object = "exampledir/exampleobject.jpg";
// 填写目标Object完整路径,例如example-new.jpg。
$save_object = "example-new.jpg";

function base64url_encode($data)
{
    return rtrim(strtr(base64_encode($data), '+/', '-_'), '=');
}

$ossClient = new OssClient($accessKeyId, $accessKeySecret, $endpoint, false);
// 如果目标图片不在指定Bucket中,需上传图片到目标Bucket。
// $ossClient->uploadFile($bucket, $object, "D:\\localpath\\exampleobject.jpg");

// 将图片缩放为固定宽高100 px后,再旋转90°。
$style = "image/resize,m_fixed,w_100,h_100/rotate,90";

$process = $style.
           '|sys/saveas'.
           ',o_'.base64url_encode($save_object).
           ',b_'.base64url_encode($bucket);

// 将处理后的图片命名为example-new.png并保存到当前Bucket。
$result = $ossClient->processObject($bucket, $object, $process);
// 打印处理结果。
print($result);
const OSS = require('ali-oss');

const client = new OSS({
  bucket: '<Your BucketName>',
  // region以杭州为例(oss-cn-hangzhou),其他region按实际情况填写。
  region: '<Your Region>',
  // 阿里云账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM用户进行API访问或日常运维,请登录RAM控制台创建RAM用户。
  accessKeyId: '<Your AccessKeyId>',
  accessKeySecret: '<Your AccessKeySecret>',
});

const sourceImage = 'sourceObject.png';
const targetImage = 'targetObject.jpg';
async function processImage(processStr, targetBucket) {
  const result = await client.processObjectSave(
    sourceImage,
    targetImage,
    processStr,
    targetBucket
  );
  console.log(result.res.status);
}

// 图片处理持久化 : 缩放
processImage("image/resize,m_fixed,w_100,h_100")

// 图片处理持久化 : 裁剪
processImage("image/crop,w_100,h_100,x_100,y_100,r_1")

// 图片处理持久化 : 旋转
processImage("image/rotate,90")

// 图片处理持久化 : 锐化
processImage("image/sharpen,100")

// 图片处理持久化 : 水印
processImage("image/watermark,text_SGVsbG8g5Zu-54mH5pyN5YqhIQ")

// 图片处理持久化 : 格式转换
processImage("image/format,jpg")

// 图片处理持久化 : 格式转换,并设置保存图片处理持久化结果的目标bucket。
processImage("image/format,jpg", "<target bucket>")
# -*- coding: utf-8 -*-
import os
import base64
import oss2
# 填写Bucket所在地域对应的Endpoint。以华东1(杭州)为例,Endpoint填写为https://oss-cn-hangzhou.aliyuncs.com。
endpoint = 'https://oss-cn-hangzhou.aliyuncs.com'
# 阿里云账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM用户进行API访问或日常运维,请登录RAM控制台创建RAM用户。
access_key_id = 'yourAccessKeyId'
access_key_secret = 'yourAccessKeySecret'
# 指定原图所在的Bucket名称。
source_bucket_name = 'srcbucket'
# 指定用于存放处理后图片的Bucket名称,该Bucket需与原图所在Bucket在同一地域。
taget_bucket_name = 'destbucket'
# 指定原图名称。如果图片不在Bucket根目录,需携带文件完整访问路径,例如example/example.jpg。
source_image_name = 'example/example.jpg'

# 指定Bucket实例,所有文件相关的方法都需要通过Bucket实例来调用。
bucket = oss2.Bucket(oss2.Auth(access_key_id, access_key_secret), endpoint, source_bucket_name)

# 将图片缩放为固定宽高100 px。
style = 'image/resize,m_fixed,w_100,h_100'
# 指定处理后图片名称。如果图片不在Bucket根目录,需携带文件完整访问路径,例如exampledir/example.jpg。
target_image_name = 'exampledir/example.jpg'
process = "{0}|sys/saveas,o_{1},b_{2}".format(style, 
    oss2.compat.to_string(base64.urlsafe_b64encode(oss2.compat.to_bytes(target_image_name))),
    oss2.compat.to_string(base64.urlsafe_b64encode(oss2.compat.to_bytes(taget_bucket_name))))
result = bucket.process_object(source_image_name, process)
print(result)
// fromBucket和toBucket分别表示源Bucket和目的Bucket名称。
// fromObjectKey和toObjectkey分别表示源Object和目标Object名称,其填写格式为指定包含文件后缀在内的完整路径,例如abc/efg/123.jpg。
// action表示图片处理操作。
ImagePersistRequest request = new ImagePersistRequest(fromBucket,fromObjectKey,toBucket,toObjectkey,action);

        OSSAsyncTask task = mOss.asyncImagePersist(request, new OSSCompletedCallback<ImagePersistRequest, ImagePersistResult>() {
            @Override
            public void onSuccess(ImagePersistRequest request, ImagePersistResult result) {
                // sucess callback
            }

            @Override
            public void onFailure(ImagePersistRequest request, ClientException clientException, ServiceException serviceException) {
                  // errror callback
            }
        });
package main

import (
    "fmt"
    "os"
    "encoding/base64"
    "github.com/aliyun/aliyun-oss-go-sdk/oss"
)

func HandleError(err error) {
    fmt.Println("Error:", err)
    os.Exit(-1)
}

func main() {
    // 创建OSSClient实例。
    // yourEndpoint填写Bucket对应的Endpoint,以华东1(杭州)为例,填写为https://oss-cn-hangzhou.aliyuncs.com。其它Region请按实际情况填写。
    // 阿里云账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM用户进行API访问或日常运维,请登录RAM控制台创建RAM用户。
    client, err := oss.New("yourEndpoint", "yourAccessKeyId", "yourAccessKeySecret")
    if err != nil {
    HandleError(err)
    }    

    // 指定原图所在Bucket的名称,例如srcbucket。
    bucketName := "srcbucket"
    bucket, err := client.Bucket(bucketName)
    if err != nil {
     HandleError(err)
    }
    // 指定原图名称。如果图片不在Bucket根目录,需携带文件完整路径,例如example/example.jpg。
    sourceImageName := "example/example.jpg"
    // 指定用于存放处理后图片的Bucket名称,该Bucket需与原图所在Bucket在同一地域。
    targetBucketName := "destbucket"
    // 指定处理后图片名称。如果图片不在Bucket根目录,需携带文件完整访问路径,例如exampledir/example.jpg。
    targetImageName = "exampledir/example.jpg"
    // 将图片缩放为固定宽高100 px后转存到指定存储空间。
    style = "image/resize,m_fixed,w_100,h_100"
    process = fmt.Sprintf("%s|sys/saveas,o_%v,b_%v", style, base64.URLEncoding.EncodeToString([]byte(targetImageName)), base64.URLEncoding.EncodeToString([]byte(targetBucketName)))
    result, err = bucket.ProcessObject(sourceImageName, process)
    if err != nil {
    HandleError(err)
    } else {
        fmt.Println(result)
    }
}                      
OSSImagePersistRequest *request = [OSSImagePersistRequest new];
request.fromBucket = _privateBucketName;
request.fromObject = OSS_IMAGE_KEY;
request.toBucket = _privateBucketName;
request.toObject = @"image_persist_key";   
request.action = @"image/resize,w_100";
//request.action = @"resize,w_100";

[[[ossClient imageActionPersist:request] continueWithBlock:^id _Nullable(OSSTask * _Nonnull task) {

    return nil;
}] waitUntilFinished];
#include <alibabacloud/oss/OssClient.h>
#include <sstream>
using namespace AlibabaCloud::OSS;

int main(void)
{
    /* 初始化OSS账号信息。*/
    /* 阿里云账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM用户进行API访问或日常运维,请登录RAM控制台创建RAM用户。*/
    std::string AccessKeyId = "yourAccessKeyId";
    std::string AccessKeySecret = "yourAccessKeySecret";
    /* 指定Bucket所在地域对应的Endpoint。以华东1(杭州)为例,Endpoint填写为https://oss-cn-hangzhou.aliyuncs.com。*/
    std::string Endpoint = "yourEndpoint";
    /* 指定Bucket名称,例如examplebucket。*/
    std::string BucketName = "examplebucket";
    /* 指定原图名称。如果图片不在Bucket根目录,需携带文件完整路径,例如example/example.jpg。*/
    std::string SourceObjectName = "example/example.jpg";
    /* 指定处理后图片名称。如果图片不在Bucket根目录,需携带文件完整访问路径,例如exampledir/example.jpg。*/
    std::string TargetObjectName = "exampledir/example.jpg";

    /* 初始化网络等资源。*/
    InitializeSdk();

    ClientConfiguration conf;
    OssClient client(Endpoint, AccessKeyId, AccessKeySecret, conf);

    /* 将图片缩放为固定宽高100 px后转存到当前Bucket。*/
    std::string Process = "image/resize,m_fixed,w_100,h_100";
    std::stringstream ss;
    ss  << Process 
    <<"|sys/saveas"
    << ",o_" << Base64EncodeUrlSafe(TargetObjectName)
    << ",b_" << Base64EncodeUrlSafe(BucketName);
    ProcessObjectRequest request(BucketName, SourceObjectName, ss.str());
    auto outcome = client.ProcessObject(request);

    /* 释放网络等资源。*/
    ShutdownSdk();
    return 0;
}

使用REST API

如果您的程序自定义要求较高,您可以直接发起REST API请求。直接发起REST API请求需要手动编写代码计算签名。

您可以通过PostObject接口调用图片处理服务时,并通过Body的方式传递x-oss-process,然后在图片处理请求中增加saveas参数将处理后的图片保存至指定Bucket。更多信息,请参见PostObject

使用saveas参数时,您需要携带以下选项:
选项 含义
o 目标Object名称,名称需经过URL Safe的Base64编码。具体操作,请参见水印编码
b 目标Bucket名称,名称需经过URL Safe的Base64编码。如果不指定目标Bucket,则默认保存至原图所在Bucket。

您可以通过以下两种方式处理图片并将图片转存至指定Bucket。

  • 使用图片处理参数处理图片并转存至指定Bucket,示例如下:
    POST /ObjectName?x-oss-process HTTP/1.1
    Host: oss-example.oss.aliyuncs.com
    Content-Length: 247
    Date: Fri, 04 May 2012 03:21:12 GMT
    Authorization: OSS qn6qrrqxo2oawuk53otf****:KU5h8YMUC78M30dXqf3JxrT****=
    
    // 将目标图片test.jpg等比缩放为宽100 px后,保存到名为test的Bucket中。
    x-oss-process=image/resize,w_100|sys/saveas,o_dGVzdC5qcGc,b_dGVzdA
  • 使用样式处理图片并转存至指定Bucket,示例如下:
    POST /ObjectName?x-oss-process HTTP/1.1
    Host: oss-example.oss.aliyuncs.com
    Content-Length: 247
    Date: Fri, 04 May 2012 03:22:13 GMT
    Authorization: OSS qn6qrrqxo2oawuk53otf****:KU5h8YMUC78M30dXqf3JxrT****=
    
    // 使用名为examplestyle的样式处理目标图片test.jpg后,保存到名为test的Bucket中。
    x-oss-process=style/examplestyle|sys/saveas,o_dGVzdC5qcGc,b_dGVzdA