低頻訪問、歸檔類型、冷歸檔或者深度冷歸檔有最低儲存時間長度的要求。在儲存不足規定時間長度的情況下,轉換Object儲存類型或提前刪除Object會產生不足規定時間長度容量費用。為避免產生不足規定時間長度容量費用,您需要瞭解不同儲存類型Object的最低儲存時間長度計算方法,確保滿足其最低儲存時間長度後再進行轉儲或者刪除。
儲存類型與最低儲存時間長度
儲存類型 | 最低儲存時間長度 | 計算方法 |
標準 | 無 | 不涉及 |
低頻訪問 | 30 | 以Object的LastModified時間開始計算 |
歸檔 | 60 | 以Object的LastModified時間開始計算 |
冷歸檔 | 180 | 以Object轉儲為冷歸檔類型的時間開始計算 |
深度冷歸檔 | 180 | 以Object轉儲為深度冷歸檔類型的時間開始計算 |
範例程式碼
以常用SDK範例程式碼為例擷取對象中繼資料,並根據對象的LastModified、TransitionTime與目前時間進行比較,以判斷是否滿足最低儲存時間長度的要求。
Java
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.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 {
// yourEndpoint填寫Bucket所在地區對應的Endpoint。
String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
// 從環境變數中擷取訪問憑證。運行本程式碼範例之前,請確保已設定環境變數OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();
// 填寫Bucket名稱。
String bucketName = "examplebucket";
// 建立OSSClient執行個體。
OSS ossClient = new OSSClientBuilder().build(endpoint, credentialsProvider);
// 指定要檢查的單個對象的完整路徑。
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("對象 '" + objectName + "' 的儲存類型為:" + storageClass
+ ", x-oss-transition-time時間為" + transitionTimeStr + "。");
}
}
// 擷取目前時間。
Date currentTime = new Date();
// 計算已儲存時間長度(天)。
long storageDuration = (currentTime.getTime() - lastModified.getTime()) / (1000 * 60 * 60 * 24);
// 列印資訊。
System.out.println("對象名稱: " + objectName);
System.out.println("儲存類型: " + storageClass);
System.out.println("建立時間: " + lastModifiedStr);
System.out.println("已儲存時間長度: " + 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("擷取 " + objectName + " 中繼資料時出現錯誤: " + e.getMessage());
System.out.println("----------------------------------------"); // 分隔字元
}
}
// 關閉OSSClient。
ossClient.shutdown();
}
}
Python
import datetime
import oss2
from oss2.credentials import EnvironmentVariableCredentialsProvider
# 從環境變數中擷取訪問憑證。運行本程式碼範例之前,請確保已設定環境變數OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
auth = oss2.ProviderAuth(EnvironmentVariableCredentialsProvider())
# 填寫Bucket所在地區對應的Endpoint。以華東1(杭州)為例,Endpoint填寫為https://oss-cn-hangzhou.aliyuncs.com。
# yourBucketName填寫儲存空間名稱。
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"對象 '{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}")
print(f"儲存類型: {storage_class}")
print(f"建立時間: {last_modified}")
print(f"已儲存時間長度: {storage_duration} 天")
# 判斷是否達到最低儲存時間長度。
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) # 分隔字元
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,
// region填寫Bucket所在地區。以華東1(杭州)為例,Region填寫為oss-cn-hangzhou。
region: "oss-cn-hangzhou",
// 填寫Bucket名稱。
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_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}`);
console.log(`儲存類型: ${storage_class}`);
console.log(`建立時間: ${last_modified}`);
console.log(`已儲存時間長度: ${storage_duration} 天`);
// 判斷是否達到最低儲存時間長度。
if (Object.keys(minimum_retention_period).includes(storage_class)) {
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_name} 中繼資料時出現錯誤:`, e);
}
}
})();
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;
// 填寫Bucket所在地區對應的Endpoint。以華東1(杭州)為例,Endpoint填寫為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 "對象名稱: $objectName\n";
echo "儲存類型: $storageClass\n";
echo "建立時間: $lastModified\n";
echo "已儲存時間長度: $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 "擷取 $objectName 中繼資料時出現錯誤: " . $e->getMessage() . "\n";
echo str_repeat("-", 40) . "\n"; // 分隔字元
}
}
} catch (OssException $e) {
printf(__FUNCTION__ . ": FAILED\n");
printf($e->getMessage() . "\n");
return;
}
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,
}
// 填寫Bucket名稱。
bucketName := "examplebucket"
for _, objectName := range objectNames {
objectName = strings.Trim(objectName, " ")
objectInfo, err := client.HeadObject(context.TODO(), &oss.HeadObjectRequest{
Bucket: oss.Ptr(bucketName),
Key: oss.Ptr(objectName),
})
if err != nil {
log.Printf("擷取 %s 中繼資料時出現錯誤: %v\n", objectName, err)
continue
}
storageClass := objectInfo.StorageClass
currentTime := time.Now().Unix()
storageDuration := (currentTime - objectInfo.LastModified.Unix()) / 60 / 60 / 24
if *storageClass == "ColdArchive" || *storageClass == "DeepColdArchive" {
if objectInfo.Headers.Get("x-oss-transition-time") != "" {
transitionTime, err := time.Parse(http.TimeFormat, objectInfo.Headers.Get("x-oss-transition-time"))
if err != nil {
fmt.Printf("Failed to parse %s x-oss-transition-time: %v\n", objectName, err)
continue
}
storageDuration = (currentTime - transitionTime.Unix()) / 60 / 60 / 24
}
}
fmt.Printf("對象名稱: %s\n", objectName)
fmt.Printf("儲存類型: %s\n", *storageClass)
fmt.Printf("建立時間: %s\n", *objectInfo.LastModified)
fmt.Printf("已儲存時間長度: %d 天\n", storageDuration)
if minimumRetentionPeriod[*storageClass] != 0 {
minRetention := minimumRetentionPeriod[*storageClass]
daysRemaining := minRetention - int(storageDuration)
fmt.Printf("%s 尚未達到最低儲存時間長度,應再儲存 %d 天,提前刪除會產生 %d 天的不足規定時間長度的容量費用。\n", objectName, daysRemaining, daysRemaining)
} else {
fmt.Printf("%s 的儲存類型未被識別。\n", objectName)
}
}
}
更多參考
以上範例程式碼示範通過head_object方法擷取單個對象的儲存類型,並根據對象的LastModified、TransitionTime與目前時間進行比較,以判斷是否滿足最低儲存時間長度的要求。如果涉及擷取多個對象,可以使用GetBucket (ListObjects)、ListObjectVersions(GetBucketVersions)、ListBucketInventory介面。