图片处理持久化

OSS会根据请求的参数实时生成图片,默认不保存处理后的图片。对于经常需要展示相同处理结果(例如缩略图、裁剪图或格式转换后的图片)的应用场景,您可以选择OSS图片处理持久化功能。图片处理持久化支持在图片处理的请求中添加转存参数,并将处理后的图片保存至指定的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.auth.*;
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";
        // 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
        EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();
        // 填写Bucket名称,例如examplebucket。
        String bucketName = "examplebucket";
        // 填写Object完整路径。Object完整路径中不能包含Bucket名称。
        String sourceImage = "exampleimage.png";

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

        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\Credentials\EnvironmentVariableCredentialsProvider;
use OSS\OssClient;

// 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
$provider = new EnvironmentVariableCredentialsProvider();
// 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), '+/', '-_'), '=');
}

$config = array(
        "provider" => $provider,
        "endpoint" => $endpoint,
    );
    $ossClient = new OssClient($config);
// 如果目标图片不在指定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({
  // yourregion填写Bucket所在地域。以华东1(杭州)为例,Region填写为oss-cn-hangzhou。
  region: 'yourregion',
  // 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
  accessKeyId: process.env.OSS_ACCESS_KEY_ID,
  accessKeySecret: process.env.OSS_ACCESS_KEY_SECRET,
  // yourbucketname填写存储空间名称。
  bucket: 'yourbucketname'
});

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);
}

// 图片处理持久化:缩放,并设置保存图片处理持久化结果的目标bucket。
processImage("image/resize,m_fixed,w_100,h_100", "target bucket")

// 图片处理持久化:裁剪,并设置保存图片处理持久化结果的目标bucket。
processImage("image/crop,w_100,h_100,x_100,y_100,r_1", "target bucket")

// 图片处理持久化:旋转,并设置保存图片处理持久化结果的目标bucket。
processImage("image/rotate,90", "target bucket")

// 图片处理持久化:锐化,并设置保存图片处理持久化结果的目标bucket。
processImage("image/sharpen,100", "target bucket")

// 图片处理持久化:水印,并设置保存图片处理持久化结果的目标bucket。
processImage("image/watermark,text_SGVsbG8g5Zu-54mH5pyN5YqhIQ", "target bucket")

// 图片处理持久化:格式转换,并设置保存图片处理持久化结果的目标bucket。
processImage("image/format,jpg", "target bucket")

// 图片处理持久化:格式转换,并设置保存图片处理持久化结果的目标bucket。
processImage("image/format,jpg", "target bucket")
# -*- coding: utf-8 -*-
import os
import base64
import oss2
from oss2.credentials import EnvironmentVariableCredentialsProvider

# 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
auth = oss2.ProviderAuth(EnvironmentVariableCredentialsProvider())
# yourEndpoint填写Bucket所在地域对应的Endpoint。以华东1(杭州)为例,Endpoint填写为https://oss-cn-hangzhou.aliyuncs.com。
# 填写Bucket名称。
bucket = oss2.Bucket(auth, 'https://oss-cn-hangzhou.aliyuncs.com', 'examplebucket')
# 指定原图所在的Bucket名称。
source_bucket_name = 'srcbucket'
# 指定用于存放处理后图片的Bucket名称,该Bucket需与原图所在Bucket在同一地域。
target_bucket_name = 'destbucket'
# 指定原图名称。如果图片不在Bucket根目录,需携带文件完整访问路径,例如example/example.jpg。
source_image_name = 'example/example.jpg'

# 将图片缩放为固定宽高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(target_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表示图片处理操作,如上面示例提到的"image/resize,m_lfit,w_100,h_100"。
ImagePersistRequest request = new ImagePersistRequest(fromBucket,fromObjectKey,toBucket,toObjectkey,action);

        OSSAsyncTask task = oss.asyncImagePersist(request, new OSSCompletedCallback<ImagePersistRequest, ImagePersistResult>() {
            @Override
            public void onSuccess(ImagePersistRequest request, ImagePersistResult result) {
                // sucess callback
                log.i("info", "Success");
            }

            @Override
            public void onFailure(ImagePersistRequest request, ClientException clientException, ServiceException serviceException) {
              // 请求异常。
              if (clientException != null) {
                  // 客户端异常,例如网络异常等。
                  clientException.printStackTrace();
              }
              if (serviceException != null) {
                  // 服务端异常。
                  Log.e("ErrorCode", serviceException.getErrorCode());
                  Log.e("RequestId", serviceException.getRequestId());
                  Log.e("HostId", serviceException.getHostId());
                  Log.e("RawMessage", serviceException.getRawMessage());
              }
            }
        });
package main

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

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

func main() {
    // 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
    provider, err := oss.NewEnvironmentVariableCredentialsProvider()
    if err != nil {
    fmt.Println("Error:", err)
    os.Exit(-1)
    }

    // 创建OSSClient实例。
    // yourEndpoint填写Bucket对应的Endpoint,以华东1(杭州)为例,填写为https://oss-cn-hangzhou.aliyuncs.com。其它Region请按实际情况填写。
    client, err := oss.New("yourEndpoint", "", "", oss.SetCredentialsProvider(&provider))
    if err != nil {
    HandleError(err)
    }

    // 指定原图所在Bucket的名称,例如srcbucket。
    bucketName := "SourceBucketName"
    bucket, err := client.Bucket(bucketName)
    if err != nil {
    HandleError(err)
    }
    // 指定原图名称。如果图片不在Bucket根目录,需携带文件完整路径,例如example/example.jpg。
    sourceImageName := "yourObjectName"
    // 指定用于存放处理后图片的Bucket名称,该Bucket需与原图所在Bucket在同一地域。
    targetBucketName := "TargetBucketName"
    // 指定处理后图片名称。如果图片不在Bucket根目录,需携带文件完整访问路径,例如exampledir/example.jpg。
    targetImageName := "TargetObjectName"
    // 将图片缩放为固定宽高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];
// 填写原图所在Bucket的名称。
request.fromBucket = @"srcbucket";
// 填写原图名称。如果图片不在Bucket根目录,需携带文件完整路径,例如exampledir/src.jpg。
request.fromObject = @"exampledir/src.jpg";
// 填写处理后图片存放的Bucket名称,该Bucket需与源Bucket在相同地域。
request.toBucket = @"destbucket";
// 填写处理后的图片名称.
request.toObject = @"exampledir/dest.jpg";
// 将图片按比例缩放至宽100 px后转存到指定Bucket。
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账号信息。*/
            
    /* 指定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;
    /* 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。*/
    auto credentialsProvider = std::make_shared<EnvironmentVariableCredentialsProvider>();
    OssClient client(Endpoint, credentialsProvider, 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);
    if (outcome.isSuccess()) {
    std::cout << "Image processed successfully." << std::endl;
    } else {
    std::cout << "Failed to process image. Error code: " << outcome.error().Code()
              << ", Message: " << outcome.error().Message()
              << ", RequestId: " << outcome.error().RequestId() << std::endl;
    }

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

使用REST API

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

使用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 qn6q**************:77Dv****************
    
    // 将目标图片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 qn6q**************:77Dv****************
    
    // 使用名为examplestyle的样式处理目标图片test.jpg后,保存到名为test的Bucket中。
    x-oss-process=style/examplestyle|sys/saveas,o_dGVzdC5qcGc,b_dGVzdA