Os objetos Infrequent Access (IA), Archive, Cold Archive e Deep Cold Archive têm uma duração mínima de armazenamento. Se você converter a classe de armazenamento de um objeto ou excluí-lo dentro desse período mínimo, será cobrado pelo uso de armazenamento dos objetos armazenados por um período inferior à duração mínima. Para evitar cobranças desnecessárias, familiarize-se com como verificar se os objetos das diferentes classes de armazenamento atendem aos requisitos de duração mínima e garanta o cumprimento desse requisito antes de converter a classe de armazenamento de um objeto ou de excluí-lo.
Classe de armazenamento e duração mínima de armazenamento
|
Classe de armazenamento |
Duração mínima de armazenamento |
Método de cálculo |
|
Standard |
N/A |
N/A |
|
Infrequent Access |
30 |
Com base no horário da última modificação dos objetos. |
|
Archive |
60 |
Com base no horário da última modificação dos objetos. |
|
Cold Archive |
180 |
Com base no horário em que as classes de armazenamento dos objetos são convertidas para Cold Archive. |
|
Deep Cold Archive |
180 |
Com base no horário em que as classes de armazenamento dos objetos são convertidas para Deep Cold Archive. |
Exemplos
O código de exemplo a seguir mostra como consultar os metadados de um objeto e comparar os valores dos parâmetros LastModified e TransitionTime com o horário atual para determinar se o objeto atende aos requisitos de duração mínima de armazenamento:
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 {
// Set yourEndpoint to the endpoint of the region where the bucket is located.
String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
// Specify the region that corresponds to the endpoint, such as cn-hangzhou.
String region = "cn-hangzhou";
// Obtain access credentials from environment variables. Before you run this code, make sure that the OSS_ACCESS_KEY_ID and OSS_ACCESS_KEY_SECRET environment variables are configured.
EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();
// Specify the bucket name.
String bucketName = "examplebucket";
// Create an OSSClient instance.
// When the OSSClient instance is no longer in use, call the shutdown method to release its resources.
ClientBuilderConfiguration clientBuilderConfiguration = new ClientBuilderConfiguration();
// Explicitly specify Signature Version 4.
clientBuilderConfiguration.setSignatureVersion(SignVersion.V4);
OSS ossClient = OSSClientBuilder.create()
.endpoint(endpoint)
.credentialsProvider(credentialsProvider)
.clientConfiguration(clientBuilderConfiguration)
.region(region)
.build();
// Specify the full paths of the objects that you want to check.
String[] objectNames = {"example.txt"};
// A map of storage classes to minimum storage durations in days.
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 {
// Obtain the object metadata.
HeadObjectRequest headObjectRequest = new HeadObjectRequest(bucketName, objectName);
ObjectMetadata objectMetadata = ossClient.headObject(headObjectRequest);
// Obtain the storage class and the last modified time.
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("The storage class of object '" + objectName + "' is " + storageClass
+ ", and the x-oss-transition-time is " + transitionTimeStr + ".");
}
}
// Obtain the current time.
Date currentTime = new Date();
// Calculate the storage duration in days.
long storageDuration = (currentTime.getTime() - lastModified.getTime()) / (1000 * 60 * 60 * 24);
// Print the information.
System.out.println("Object Name: " + objectName);
System.out.println("Storage Class: " + storageClass);
System.out.println("Last Modified Time: " + lastModifiedStr);
System.out.println("Storage Duration: " + storageDuration + " days");
// Check whether the minimum storage duration is met.
if (minimumRetentionPeriod.containsKey(storageClass)) {
int minRetention = minimumRetentionPeriod.get(storageClass);
if (storageDuration < minRetention) {
int daysRemaining = minRetention - (int) storageDuration;
System.out.println(objectName + " has not met the minimum storage duration. It must be stored for another " + daysRemaining + " days. If you delete the object earlier, you are charged for storage fees for the remaining "
+ daysRemaining + " days of the minimum retention period.");
} else {
int daysExceeded = (int) storageDuration - minRetention;
System.out.println(objectName + " has met the minimum storage duration. The exceeded duration is " + daysExceeded + " days. No fees are charged for early deletion.");
}
} else {
System.out.println("The storage class of " + objectName + " is not recognized.");
}
System.out.println("----------------------------------------"); // Separator
} catch (Exception e) {
e.printStackTrace();
System.out.println("An error occurred while obtaining the metadata of " + objectName + ": " + e.getMessage());
System.out.println("----------------------------------------"); // Separator
}
}
// Shut down the OSSClient.
ossClient.shutdown();
}
}
Python
import datetime
import oss2
from oss2.credentials import EnvironmentVariableCredentialsProvider
# Obtain access credentials from environment variables. Before you run the sample code, make sure that the OSS_ACCESS_KEY_ID and OSS_ACCESS_KEY_SECRET environment variables are configured.
auth = oss2.ProviderAuth(EnvironmentVariableCredentialsProvider())
# Specify the endpoint of the region in which the bucket is located. For example, if the bucket is located in the China (Hangzhou) region, set the endpoint to https://oss-cn-hangzhou.aliyuncs.com.
# Specify the name of the bucket.
bucket = oss2.Bucket(auth, 'https://oss-cn-hangzhou.aliyuncs.com', 'examplebucket')
# Specify the full path of the single object.
object_names = ['example.txt']
# The mapping between the storage class and the minimum storage duration. Unit: days.
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:
# Query all object metadata using the head_object method.
object_info = bucket.head_object(object_name)
# Query the storage class and last modified time of the object.
storage_class = object_info.headers['x-oss-storage-class']
last_modified = object_info.headers['Last-Modified']
# Change the last modified time to the datetime object.
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}.")
# Query the current time.
current_time = datetime.datetime.now()
# Calculate the storage duration of the object. Unit: days.
storage_duration = (current_time - last_modified_time).days
# Display the object information.
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")
# Determine whether the object meets the minimum storage duration requirements.
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} does not meet the minimum storage duration requirements. The object needs to be stored for another {days_remaining} days. If you delete the object, you are charged {days_remaining} days of the storage usage for the object that is stored for less than the minimum storage duration.")
else:
days_exceeded = storage_duration - min_retention
print(f"{object_name} meets the minimum storage duration requirements. The object is stored {days_exceeded} days more than the minimum storage duration. You are not charged for the storage usage for the object that is stored for less than the minimum storage duration.")
else:
print(f"The storage class of {object_name} is not recognized.")
print("-" * 40) # The delimiter.
except Exception as e:
print(f "An error occurred when I query the metadata of {object_name}: {str(e)}")
print("-" * 40) # The delimiter
Node.js
const OSS = require("ali-oss");
// Obtain access credentials from environment variables. Before running this code sample, make sure that the OSS_ACCESS_KEY_ID and OSS_ACCESS_KEY_SECRET environment variables are configured.
const config = {
accessKeyId: process.env.OSS_ACCESS_KEY_ID,
accessKeySecret: process.env.OSS_ACCESS_KEY_SECRET,
// Set region to the region where the bucket is located. For example, if the bucket is in the China (Hangzhou) region, set region to oss-cn-hangzhou.
region: "oss-cn-hangzhou",
// Specify the bucket name.
bucket: "examplebucket",
};
const client = new OSS(config);
// Mapping between storage classes and minimum storage durations in days.
const minimum_retention_period = {
Standard: 0,
IA: 30,
Archive: 60,
ColdArchive: 180,
DeepColdArchive: 180,
};
// Calculate the difference between two dates in days.
function getDays(date1, date2) {
if (!(date1 instanceof Date) || !(date2 instanceof Date)) {
throw new Error("Valid Date objects must be passed.");
}
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);
}
// Specify the full path of the object to check.
const object_names = ["example.jpg"];
(async () => {
for (const object_name of object_names) {
try {
// Obtain all metadata of the object using the head method.
const object_info = await client.head(object_name);
const { headers } = object_info.res;
// Obtain the storage class and the last modified time.
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 = `The storage class of object '${object_name}' is ${storage_class}, but the x-oss-transition-time is ${transition_time_str}. The x-oss-transition-time header is available only for objects transitioned to Cold Archive or Deep Cold Archive using lifecycle rules.`;
throw new Error(errorStr);
}
}
const current_time = new Date(); // Obtain the current time.
const storage_duration = getDays(current_time, last_modified_time); // Calculate the storage duration in days.
// Print the information.
console.log(`Object name: ${object_name}`);
console.log(`Storage class: ${storage_class}`);
console.log(`Last modified time: ${last_modified}`);
console.log(`Storage duration: ${storage_duration} days`);
// Check whether the minimum storage duration is met.
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} has not met the minimum storage duration. Deleting the object now will incur fees for the remaining ${days_remaining} days of the minimum storage period.`
);
} else {
const days_exceeded = storage_duration - min_retention;
console.log(
`${object_name} has met the minimum storage duration. The storage duration has exceeded the minimum by ${days_exceeded} days. No early deletion fees will be incurred if you delete the object.`
);
}
} else console.log(`The storage class of ${object_name} is not recognized.`);
} catch (e) {
console.log(`An error occurred while obtaining the metadata of ${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;
// Specify the endpoint of the region where the bucket is located. For example, if the bucket is in the China (Hangzhou) region, set the endpoint to https://oss-cn-hangzhou.aliyuncs.com.
$endpoint = 'http://oss-cn-hangzhou.aliyuncs.com';
// Specify the bucket name.
$bucketName = 'examplebucket';
// Create an OssClient instance.
try {
// Obtain access credentials from environment variables. Before you run this sample code, make sure that the OSS_ACCESS_KEY_ID and OSS_ACCESS_KEY_SECRET environment variables are set.
$provider = new EnvironmentVariableCredentialsProvider();
$config = array(
"provider" => $provider,
"endpoint" => $endpoint,
);
$ossClient = new OssClient($config);
// Specify the full path of the object that you want to check.
$objectNames = ['example.txt'];
$minimumRetentionPeriod = [
'Standard' => 0,
'IA' => 30,
'Archive' => 60,
'ColdArchive' => 180,
'DeepColdArchive' => 180,
];
foreach ($objectNames as $objectName) {
$objectName = trim($objectName);
try {
// Obtain all the metadata of the object using the getObjectMeta method.
$objectInfo = $ossClient->getObjectMeta($bucketName, $objectName);
// Obtain the storage class and the last modified time.
$storageClass = $objectInfo['x-oss-storage-class'];
$lastModified = $objectInfo['last-modified'];
// Convert the last modified time to a UNIX timestamp.
$lastModifiedTime = strtotime($lastModified);
if (in_array($storageClass, array("ColdArchive", "DeepColdArchive")) && isset($objectInfo["x-oss-transition-time"])) {
$lastModifiedTime = strtotime($objectInfo["x-oss-transition-time"]);
}
// Get the current time.
$currentTime = time();
// Calculate the storage duration in days.
$storageDuration = floor(($currentTime - $lastModifiedTime) / (60 * 60 * 24));
// Print the information.
echo "Object name: $objectName\n";
echo "Storage class: $storageClass\n";
echo "Last modified: $lastModified\n";
echo "Storage duration: $storageDuration days\n";
// Check whether the minimum storage duration is met.
if (isset($minimumRetentionPeriod[$storageClass])) {
$minRetention = $minimumRetentionPeriod[$storageClass];
if ($storageDuration < $minRetention) {
$daysRemaining = $minRetention - $storageDuration;
echo "$objectName has not met the minimum storage duration. It must be stored for another $daysRemaining days. Deleting it early will incur fees for the remaining $daysRemaining days of the minimum storage period.\n";
} else {
$daysExceeded = $storageDuration - $minRetention;
echo "$objectName has met the minimum storage duration, exceeding the requirement by $daysExceeded days. Deleting the object will not incur early deletion fees.\n";
}
} else {
echo "The storage class of $objectName was not recognized.\n";
}
echo str_repeat("-", 40) . "\n"; // Separator
} catch (OssException $e) {
echo "An error occurred while obtaining the metadata of $objectName: " . $e->getMessage() . "\n";
echo str_repeat("-", 40) . "\n"; // Separator
}
}
} 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)
// Specify the full path of the object to check.
objectNames := []string{"example.txt"}
// Define the minimum storage duration in days for each storage class.
minimumRetentionPeriod := map[string]int{
"Standard": 0,
"IA": 30,
"Archive": 60,
"ColdArchive": 180,
"DeepColdArchive": 180,
}
// Set bucketName to the name of the bucket.
bucketName := "examplebucket"
for _, objectName := range objectNames {
objectName = strings.TrimSpace(objectName)
if objectName == "" {
continue
}
// Get object metadata.
objectInfo, err := client.HeadObject(context.TODO(), &oss.HeadObjectRequest{
Bucket: oss.Ptr(bucketName),
Key: oss.Ptr(objectName),
})
if err != nil {
log.Printf("An error occurred while getting metadata for %s: %v\n", objectName, err)
continue
}
// Check if storageClass is empty.
if objectInfo.StorageClass == nil {
log.Printf("Warning: The storage class of %s is empty. Skipping check.\n", objectName)
continue
}
storageClass := *objectInfo.StorageClass
currentTime := time.Now().Unix()
// Calculate the storage duration in days.
storageDuration := (currentTime - objectInfo.LastModified.Unix()) / (60 * 60 * 24)
// For Cold Archive and Deep Cold Archive, calculate from the transition time if it exists.
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: Failed to parse x-oss-transition-time for %s: %v. Calculating based on creation time.\n", objectName, err)
} else {
storageDuration = (currentTime - transitionTime.Unix()) / (60 * 60 * 24)
}
}
}
// Print basic object information.
fmt.Printf("Object name: %s\n", objectName)
fmt.Printf("Storage class: %s\n", storageClass)
fmt.Printf("Creation time: %s\n", objectInfo.LastModified.Format("2006-01-02 15:04:05"))
fmt.Printf("Storage duration: %d days\n", storageDuration)
// Check if the minimum storage duration is met.
minRetention, exists := minimumRetentionPeriod[storageClass]
if !exists {
fmt.Printf("The storage class of %s is not recognized.\n", objectName)
fmt.Println("----------------------------------------")
continue
}
if minRetention == 0 {
// The Standard storage class has no minimum storage duration.
fmt.Printf("The storage class of %s is Standard, which has no minimum storage duration. No fees for insufficient storage duration will be incurred upon deletion.\n", objectName)
} else {
daysRemaining := minRetention - int(storageDuration)
if daysRemaining > 0 {
// The minimum storage duration is not met.
fmt.Printf("%s has not met the minimum storage duration. It must be stored for another %d days. Deleting it early will incur fees for %d days of insufficient storage duration.\n",
objectName, daysRemaining, daysRemaining)
} else {
// The minimum storage duration is met.
fmt.Printf("%s has met the minimum storage duration (stored for %d days, required %d days). No fees for insufficient storage duration will be incurred upon deletion.\n",
objectName, int(storageDuration), minRetention)
}
}
fmt.Println("----------------------------------------")
}
}
Referências
O código de exemplo anterior demonstra como consultar os metadados de um objeto pelo método head_object e comparar os valores dos parâmetros LastModified e TransitionTime com o horário atual para determinar se o objeto atende aos requisitos de duração mínima de armazenamento: se você quiser verificar se vários objetos cumprem esses requisitos, chame as operações GetBucket (ListObjects), ListObjectVersions(GetBucketVersions) e ListBucketInventory.