低頻度アクセス (IA)、アーカイブ、コールドアーカイブストレージ、ディープコールドアーカイブストレージの各ストレージクラスには、それぞれ最小保存期間が定められています。この期間を満たす前にオブジェクトを削除したり、ストレージクラスを変更したりすると、OSS は最小保存期間を満たさない期間分のストレージ利用に対して課金します。
予期しない課金を回避するためには、オブジェクトを削除またはストレージクラスを変更する前に、そのオブジェクトが最小保存期間の要件を満たしているかどうかを確認してください。
ストレージクラス別の最小保存期間
| ストレージクラス | 最小保存期間 | 期間の算出開始時刻 |
|---|---|---|
| 標準 | なし | 該当なし |
| 低頻度アクセス (IA) | 30 日間 | 最終更新時刻 |
| アーカイブ | 60 日間 | 最終更新時刻 |
| コールドアーカイブストレージ | 180 日間 | ストレージクラスをコールドアーカイブストレージに変更した時刻 |
| ディープコールドアーカイブストレージ | 180 日間 | ストレージクラスをディープコールドアーカイブストレージに変更した時刻 |
重要
早期削除による課金が発生する操作は、以下の 2 種類です:オブジェクトの削除とストレージクラスの変更。いずれの操作を行う場合も、事前にオブジェクトが最小保存期間の要件を満たしているかどうかを確認してください。
オブジェクトが最小保存期間の要件を満たしているかを確認する
以下のコード例では、`HeadObject` 操作を使用してオブジェクトのメタデータを照会し、`Last-Modified` ヘッダーまたは `x-oss-transition-time` ヘッダーの値を現在時刻と比較しています。コールドアーカイブストレージおよびディープコールドアーカイブストレージのオブジェクトについては、期間の算出開始時刻は `x-oss-transition-time`(ストレージクラス変更時刻)であり、`Last-Modified` ではありません。
Python
import datetime
import oss2
from oss2.credentials import EnvironmentVariableCredentialsProvider
# アクセス認証情報を環境変数から取得します。サンプルコードを実行する前に、OSS_ACCESS_KEY_ID および OSS_ACCESS_KEY_SECRET 環境変数が設定されていることを確認してください。
auth = oss2.ProviderAuth(EnvironmentVariableCredentialsProvider())
# バケットが配置されているリージョンのエンドポイントを指定します。たとえば、バケットが中国 (杭州) リージョンにある場合、エンドポイントは https://oss-cn-hangzhou.aliyuncs.com となります。
# バケット名を指定します。
bucket = oss2.Bucket(auth, 'https://oss-cn-hangzhou.aliyuncs.com', 'examplebucket')
# 対象となる単一オブジェクトの完全なパスを指定します。
object_names = ['example.txt']
# ストレージクラスと最小保存期間(単位:日)のマッピング。
minimum_retention_period = {
'Standard': 0,
'IA': 30,
'Archive': 60,
'ColdArchive': 180,
'DeepColdArchive': 180
}
for object_name in object_names:
object_name = object_name.strip()
try:
# head_object メソッドを使用して、オブジェクトの全メタデータを照会します。
object_info = bucket.head_object(object_name)
# オブジェクトのストレージクラスと最終更新時刻を照会します。
storage_class = object_info.headers['x-oss-storage-class']
last_modified = object_info.headers['Last-Modified']
# 最終更新時刻を datetime オブジェクトに変換します。
last_modified_time = datetime.datetime.strptime(last_modified, '%a, %d %b %Y %H:%M:%S GMT')
transition_time_str = object_info.headers.get('x-oss-transition-time')
transition_time = None
if storage_class == 'ColdArchive' or storage_class == 'DeepColdArchive':
if transition_time_str:
last_modified_time = datetime.datetime.strptime(transition_time_str, "%a, %d %b %Y %H:%M:%S %Z")
else:
raise Exception(f"Storage class of '{object_name}': {storage_class}. x-oss-transition-time: {transition_time_str}.")
# 現在時刻を照会します。
current_time = datetime.datetime.now()
# オブジェクトの保存期間(単位:日)を計算します。
storage_duration = (current_time - last_modified_time).days
# オブジェクト情報を表示します。
print(f"Object name: {object_name}")
print(f"Storage class: {storage_class}")
print(f"Created at: {last_modified}")
print(f"Storage duration: {storage_duration} days")
# オブジェクトが最小保存期間の要件を満たしているかを判定します。
if storage_class in minimum_retention_period:
min_retention = minimum_retention_period[storage_class]
if storage_duration < min_retention:
days_remaining = min_retention - storage_duration
print(f"{object_name} は最小保存期間の要件を満たしていません。オブジェクトをさらに {days_remaining} 日間保存する必要があります。このオブジェクトを削除すると、最小保存期間を満たさない期間分({days_remaining} 日分)のストレージ利用に対して課金されます。")
else:
days_exceeded = storage_duration - min_retention
print(f"{object_name} は最小保存期間の要件を満たしています。オブジェクトは最小保存期間よりも {days_exceeded} 日間長く保存されています。最小保存期間を満たさない期間分のストレージ利用に対しては課金されません。")
else:
print(f"{object_name} のストレージクラスは認識されていません。")
print("-" * 40) # 区切り文字。
except Exception as e:
print(f"{object_name} のメタデータ照会中にエラーが発生しました:{str(e)}")
print("-" * 40) # 区切り文字Java
import com.aliyun.oss.ClientBuilderConfiguration;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.common.auth.CredentialsProviderFactory;
import com.aliyun.oss.common.auth.EnvironmentVariableCredentialsProvider;
import com.aliyun.oss.common.comm.SignVersion;
import com.aliyun.oss.common.utils.DateUtil;
import com.aliyun.oss.model.ObjectMetadata;
import com.aliyun.oss.model.HeadObjectRequest;
import com.aliyuncs.exceptions.ClientException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
public class Demo {
public static void main(String[] args) throws ClientException {
// バケットが配置されているリージョンのエンドポイントを指定します。
String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
// エンドポイントに対応するリージョン ID を指定します(例:cn-hangzhou)。
String region = "cn-hangzhou";
// アクセス認証情報を環境変数から取得します。サンプルコードを実行する前に、OSS_ACCESS_KEY_ID および OSS_ACCESS_KEY_SECRET 環境変数が設定されていることを確認してください。
EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();
// バケット名を指定します。
String bucketName = "examplebucket";
// OSSClient インスタンスを作成します。
// OSSClient を使用しなくなった際には、shutdown メソッドを呼び出してリソースを解放してください。
ClientBuilderConfiguration clientBuilderConfiguration = new ClientBuilderConfiguration();
// V4 署名アルゴリズムを明示的に宣言します。
clientBuilderConfiguration.setSignatureVersion(SignVersion.V4);
OSS ossClient = OSSClientBuilder.create()
.endpoint(endpoint)
.credentialsProvider(credentialsProvider)
.clientConfiguration(clientBuilderConfiguration)
.region(region)
.build();
// オブジェクトの完全なパスを指定します。
String[] objectNames = {"example.txt"};
// ストレージクラスと最小保存期間(単位:日)のマッピング。
Map<String, Integer> minimumRetentionPeriod = new HashMap<>();
minimumRetentionPeriod.put("Standard", 0);
minimumRetentionPeriod.put("IA", 30);
minimumRetentionPeriod.put("Archive", 60);
minimumRetentionPeriod.put("ColdArchive", 180);
minimumRetentionPeriod.put("DeepColdArchive", 180);
for (String objectName : objectNames) {
objectName = objectName.trim();
try {
// オブジェクトのメタデータを照会します。
HeadObjectRequest headObjectRequest = new HeadObjectRequest(bucketName, objectName);
ObjectMetadata objectMetadata = ossClient.headObject(headObjectRequest);
// オブジェクトのストレージクラスと最終更新時刻を照会します。
String storageClass = String.valueOf(objectMetadata.getObjectStorageClass());
String lastModifiedStr = objectMetadata.getLastModified().toString();
Date lastModified = objectMetadata.getLastModified();
if ("ColdArchive".equals(storageClass) || "DeepColdArchive".equals(storageClass)) {
Object transitionTimeObj = objectMetadata.getRawMetadata().get("x-oss-transition-time");
String transitionTimeStr = String.valueOf(transitionTimeObj);
Date transitionTime = DateUtil.parseRfc822Date(transitionTimeStr);
if (transitionTime != null) {
lastModified = transitionTime;
} else {
throw new Exception("Object '" + objectName + "' のストレージクラス:" + storageClass
+ "、x-oss-transition-time:" + transitionTimeStr + "。");
}
}
// 現在時刻を照会します。
Date currentTime = new Date();
// オブジェクトの保存期間(単位:日)を計算します。
long storageDuration = (currentTime.getTime() - lastModified.getTime()) / (1000 * 60 * 60 * 24);
// オブジェクト情報を表示します。
System.out.println("Object name: " + objectName);
System.out.println("Storage class: " + storageClass);
System.out.println("Created at: " + lastModifiedStr);
System.out.println("Storage duration: " + storageDuration + " 日");
// オブジェクトが最小保存期間の要件を満たしているかを判定します。
if (minimumRetentionPeriod.containsKey(storageClass)) {
int minRetention = minimumRetentionPeriod.get(storageClass);
if (storageDuration < minRetention) {
int daysRemaining = minRetention - (int) storageDuration;
System.out.println(objectName + " は最小保存期間の要件を満たしていません。オブジェクトをさらに " + daysRemaining + " 日間保存する必要があります。このオブジェクトを削除すると、最小保存期間を満たさない期間分(" + daysRemaining + " 日分)のストレージ利用に対して課金されます。");
} else {
int daysExceeded = (int) storageDuration - minRetention;
System.out.println(objectName + " は最小保存期間の要件を満たしています。オブジェクトは最小保存期間よりも " + daysExceeded + " 日間長く保存されています。最小保存期間を満たさない期間分のストレージ利用に対しては課金されません。");
}
} else {
System.out.println(objectName + " のストレージクラスは認識されていません。");
}
System.out.println("----------------------------------------"); // 区切り文字。
} catch (Exception e) {
e.printStackTrace();
System.out.println("Object " + objectName + " のメタデータ照会中にエラーが発生しました:" + e.getMessage());
System.out.println("----------------------------------------"); // 区切り文字。
}
}
// OSSClient インスタンスをシャットダウンします。
ossClient.shutdown();
}
}Go
package main
import (
"context"
"fmt"
"log"
"net/http"
"strings"
"time"
"github.com/aliyun/alibabacloud-oss-go-sdk-v2/oss"
"github.com/aliyun/alibabacloud-oss-go-sdk-v2/oss/credentials"
)
func main() {
cfg := oss.LoadDefaultConfig().
WithCredentialsProvider(credentials.NewEnvironmentVariableCredentialsProvider()).
WithRegion("cn-hangzhou").
WithEndpoint("https://oss-cn-hangzhou.aliyuncs.com")
client := oss.NewClient(cfg)
// 確認対象のオブジェクトの完全なパスを指定します。
objectNames := []string{"example.txt"}
// 各ストレージクラスの最小保存期間(単位:日)を定義します。
minimumRetentionPeriod := map[string]int{
"Standard": 0,
"IA": 30,
"Archive": 60,
"ColdArchive": 180,
"DeepColdArchive": 180,
}
// バケット名を指定します。
bucketName := "examplebucket"
for _, objectName := range objectNames {
objectName = strings.TrimSpace(objectName)
if objectName == "" {
continue
}
// オブジェクトのメタデータを照会します。
objectInfo, err := client.HeadObject(context.TODO(), &oss.HeadObjectRequest{
Bucket: oss.Ptr(bucketName),
Key: oss.Ptr(objectName),
})
if err != nil {
log.Printf("Object %s のメタデータ照会中にエラーが発生しました:%v\n", objectName, err)
continue
}
// storageClass が nil の場合をチェックします。
if objectInfo.StorageClass == nil {
log.Printf("Warning: %s のストレージクラスが nil です。このオブジェクトはスキップされます。\n", objectName)
continue
}
storageClass := *objectInfo.StorageClass
currentTime := time.Now().Unix()
// 保存期間を日単位で計算します。
storageDuration := (currentTime - objectInfo.LastModified.Unix()) / (60 * 60 * 24)
// コールドアーカイブストレージおよびディープコールドアーカイブストレージの場合、利用可能な場合はトランジション時刻を使用します。
if storageClass == "ColdArchive" || storageClass == "DeepColdArchive" {
transitionTimeStr := objectInfo.Headers.Get("x-oss-transition-time")
if transitionTimeStr != "" {
transitionTime, err := time.Parse(http.TimeFormat, transitionTimeStr)
if err != nil {
log.Printf("Warning: %s の x-oss-transition-time の解析に失敗しました:%v。代わりに作成時刻を使用します。\n", objectName, err)
} else {
storageDuration = (currentTime - transitionTime.Unix()) / (60 * 60 * 24)
}
}
}
// オブジェクトの基本情報を表示します。
fmt.Printf("Object name: %s\n", objectName)
fmt.Printf("Storage class: %s\n", storageClass)
fmt.Printf("Created at: %s\n", objectInfo.LastModified.Format("2006-01-02 15:04:05"))
fmt.Printf("Storage duration: %d 日\n", storageDuration)
// 最小保存期間の要件を満たしているかを確認します。
minRetention, exists := minimumRetentionPeriod[storageClass]
if !exists {
fmt.Printf("%s のストレージクラスは認識されていません。\n", objectName)
fmt.Println("----------------------------------------")
continue
}
if minRetention == 0 {
// 標準ストレージクラスには最小保存期間の要件はありません。
fmt.Printf("%s は標準ストレージクラスを使用しており、最小保存期間の要件はありません。このオブジェクトを削除しても、保存期間不足による課金は発生しません。\n", objectName)
} else {
daysRemaining := minRetention - int(storageDuration)
if daysRemaining > 0 {
// オブジェクトは最小保存期間の要件を満たしていません。
fmt.Printf("%s は最小保存期間の要件を満たしていません。オブジェクトをさらに %d 日間保存する必要があります。この時点でオブジェクトを削除すると、最小保存期間を満たさない期間分(%d 日分)のストレージ利用に対して課金されます。\n",
objectName, daysRemaining, daysRemaining)
} else {
// オブジェクトは最小保存期間の要件を満たしています。
fmt.Printf("%s は最小保存期間の要件を満たしています(保存期間:%d 日、必要期間:%d 日)。このオブジェクトを削除しても、保存期間不足による課金は発生しません。\n",
objectName, int(storageDuration), minRetention)
}
}
fmt.Println("----------------------------------------")
}
}PHP
<?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;
use OSS\Core\OssException;
// バケットが配置されているリージョンのエンドポイントを指定します。たとえば、バケットが中国 (杭州) リージョンにある場合、エンドポイントは https://oss-cn-hangzhou.aliyuncs.com となります。
$endpoint = 'http://oss-cn-hangzhou.aliyuncs.com';
// バケット名を指定します。
$bucketName = 'examplebucket';
// OSSClient インスタンスを作成します。
try {
// アクセス認証情報を環境変数から取得します。サンプルコードを実行する前に、OSS_ACCESS_KEY_ID および OSS_ACCESS_KEY_SECRET 環境変数が設定されていることを確認してください。
$provider = new EnvironmentVariableCredentialsProvider();
$config = array(
"provider" => $provider,
"endpoint" => $endpoint,
);
$ossClient = new OssClient($config);
// オブジェクトの完全なパスを指定します。
$objectNames = ['example.txt'];
$minimumRetentionPeriod = [
'Standard' => 0,
'IA' => 30,
'Archive' => 60,
'ColdArchive' => 180,
'DeepColdArchive' => 180,
];
foreach ($objectNames as $objectName) {
$objectName = trim($objectName);
try {
// headObject メソッドを使用して、オブジェクトの全メタデータを照会します。
$objectInfo = $ossClient->getObjectMeta($bucketName, $objectName);
// オブジェクトのストレージクラスと最終更新時刻を照会します。
$storageClass = $objectInfo['x-oss-storage-class'];
$lastModified = $objectInfo['last-modified'];
// オブジェクトの最終更新時刻をタイムスタンプに変換します。
$lastModifiedTime = strtotime($lastModified);
if (in_array($storageClass, array("ColdArchive", "DeepColdArchive")) && isset($objectInfo["x-oss-transition-time"])) {
$lastModifiedTime = strtotime($objectInfo["x-oss-transition-time"]);
}
// 現在時刻を照会します。
$currentTime = time();
// オブジェクトの保存期間(単位:日)を計算します。
$storageDuration = floor(($currentTime - $lastModifiedTime) / (60 * 60 * 24));
// オブジェクト情報を表示します。
echo "Object name: $objectName\n";
echo "Storage class: $storageClass\n";
echo "Created at: $lastModified\n";
echo "Storage duration: $storageDuration 日\n";
// オブジェクトが最小保存期間の要件を満たしているかを判定します。
if (isset($minimumRetentionPeriod[$storageClass])) {
$minRetention = $minimumRetentionPeriod[$storageClass];
if ($storageDuration < $minRetention) {
$daysRemaining = $minRetention - $storageDuration;
echo "$objectName は最小保存期間の要件を満たしていません。オブジェクトをさらに $daysRemaining 日間保存する必要があります。このオブジェクトを削除すると、最小保存期間を満たさない期間分($daysRemaining 日分)のストレージ利用に対して課金されます。\n";
} else {
$daysExceeded = $storageDuration - $minRetention;
echo "$objectName は最小保存期間の要件を満たしています。オブジェクトは最小保存期間よりも $daysExceeded 日間長く保存されています。最小保存期間を満たさない期間分のストレージ利用に対しては課金されません。\n";
}
} else {
echo "$objectName のストレージクラスは認識されていません。\n";
}
echo str_repeat("-", 40) . "\n"; // 区切り文字。
} catch (OssException $e) {
echo "Object $objectName のメタデータ照会中にエラーが発生しました:" . $e->getMessage() . "\n";
echo str_repeat("-", 40) . "\n"; // 区切り文字。
}
}
} catch (OssException $e) {
printf(__FUNCTION__ . ": FAILED\n");
printf($e->getMessage() . "\n");
return;
}Node.js
const OSS = require("ali-oss");
// アクセス認証情報を環境変数から取得します。サンプルコードを実行する前に、OSS_ACCESS_KEY_ID および OSS_ACCESS_KEY_SECRET 環境変数が設定されていることを確認してください。
const config = {
accessKeyId: process.env.OSS_ACCESS_KEY_ID,
accessKeySecret: process.env.OSS_ACCESS_KEY_SECRET,
// バケットが配置されているリージョンを指定します。たとえば、バケットが中国 (杭州) リージョンにある場合、リージョンは oss-cn-hangzhou となります。
region: "oss-cn-hangzhou",
// バケット名を指定します。
bucket: "examplebucket",
};
const client = new OSS(config);
// ストレージクラスと最小保存期間(単位:日)のマッピング。
const minimum_retention_period = {
Standard: 0,
IA: 30,
Archive: 60,
ColdArchive: 180,
DeepColdArchive: 180,
};
// 日単位での時間差を計算します。
function getDays(date1, date2) {
if (!(date1 instanceof Date) || !(date2 instanceof Date)) {
throw new Error("有効な Date オブジェクトを渡す必要があります");
}
const timestamp1 = date1.getTime();
const timestamp2 = date2.getTime();
const diffInMilliseconds = Math.abs(timestamp2 - timestamp1);
const diffInDays = diffInMilliseconds / (1000 * 60 * 60 * 24);
return Math.round(diffInDays);
}
// オブジェクトの完全なパスを指定します。
const object_names = ["example.jpg"];
(async () => {
for (const object_name of object_names) {
try {
// head メソッドを使用して、オブジェクトの全メタデータを照会します。
const object_info = await client.head(object_name);
const { headers } = object_info.res;
// オブジェクトのストレージクラスと最終更新時刻を照会します。
const storage_class = headers["x-oss-storage-class"];
const last_modified = headers["last-modified"];
let last_modified_time = new Date(last_modified);
const transition_time_str = headers["x-oss-transition-time"];
if (["ColdArchive", "DeepColdArchive"].includes(storage_class)) {
if (transition_time_str)
last_modified_time = new Date(transition_time_str);
else {
const errorStr = `Object '${object_name}' のストレージクラス:${storage_class}。x-oss-transition-time:${transition_time_str}。x-oss-transition-time は、ライフサイクルルールに基づいてストレージクラスがコールドアーカイブストレージまたはディープコールドアーカイブストレージに変更されたオブジェクトのみで利用可能です。`;
throw new Error(errorStr);
}
}
const current_time = new Date(); // 現在時刻を照会します。
const storage_duration = getDays(current_time, last_modified_time); // オブジェクトの保存期間(単位:日)を計算します。
// オブジェクト情報を表示します。
console.log(`Object name: ${object_name}`);
console.log(`Storage class: ${storage_class}`);
console.log(`Created at: ${last_modified}`);
console.log(`Storage duration: ${storage_duration} 日`);
// オブジェクトが最小保存期間の要件を満たしているかを判定します。
if (Object.keys(minimum_retention_period).includes(storage_class)) {
const min_retention = minimum_retention_period[storage_class];
if (storage_duration < min_retention) {
const days_remaining = min_retention - storage_duration;
console.log(
`${object_name} は最小保存期間の要件を満たしていません。オブジェクトをさらに ${days_remaining} 日間保存する必要があります。このオブジェクトを削除すると、最小保存期間を満たさない期間分(${days_remaining} 日分)のストレージ利用に対して課金されます。`
);
} else {
const days_exceeded = storage_duration - min_retention;
console.log(
`${object_name} は最小保存期間の要件を満たしています。オブジェクトは最小保存期間よりも ${days_exceeded} 日間長く保存されています。最小保存期間を満たさない期間分のストレージ利用に対しては課金されません。`
);
}
} else {
console.log(`${object_name} のストレージクラスは認識されていません。`);
}
} catch (e) {
console.log(`Object ${object_name} のメタデータ照会中にエラーが発生しました:`, e);
}
}
})();複数のオブジェクトに対する最小保存期間の確認
複数のオブジェクトを一度に確認するには、`GetBucket (ListObjects)`、`ListObjectVersions (GetBucketVersions)`、または `ListBucketInventory` 操作を使用して、オブジェクトのメタデータを一括で取得します。