This topic describes how to use temporary access credentials provided by Security Token Service (STS) or a signed URL to authorize temporary access to Object Storage Service (OSS) resources.
Usage notes
A validity period must be specified for temporary access credentials obtained from STS and a signed URL. When you use temporary access credentials to generate a signed URL that is used to perform operations, such as object upload and download, the minimum validity period takes precedence. For example, you can set the validity period of the temporary access credentials that are provided by STS to 1,200 seconds and the validity period of the signed URL generated by using the credentials to 3,600 seconds. In this case, you cannot use the signed URL to upload objects after the temporary access credentials expire, even if the signed URL is within the validity period.
In this topic, access credentials are obtained from environment variables. For more information about how to configure access credentials, see Configure access credentials.
In this topic, the public endpoint of the China (Hangzhou) region is used. If you want to access OSS by using other Alibaba Cloud services in the same region as OSS, use an internal endpoint, such as https://oss-cn-hangzhou-internal.aliyuncs.com. For more information about OSS regions and endpoints, see Regions, endpoints and open ports.
In this topic, an OSS public endpoint is used to create an OSSClient instance. If you want to create an OSSClient instance by using custom domain names or STS, see Create an OSSClient instance.
Use STS to authorize temporary access
You can use STS to authorize temporary access to OSS. STS is a web service that provides temporary access tokens for users. You can use STS to grant temporary access credentials that have a custom validity period and custom permissions to a third-party application or a RAM user that is managed by you. For more information about STS, see What is STS?.
STS provides the following benefits:
You need to only generate a temporary access token and send the access token to a third-party application. You do not need to provide your AccessKey pair to the third-party application. You can specify the access permissions and validity period of this token.
The token automatically expires after the validity period ends. Therefore, you do not need to manually revoke the access permissions of a token.
To access OSS by using temporary access credentials provided by STS, perform the following operations:
Obtain temporary access credentials.
Temporary access credentials contain a security token and a temporary AccessKey pair. An AccessKey pair consists of an AccessKey ID and an AccessKey secret. The validity period of temporary access credentials is in seconds. The minimum validity period of temporary access credentials is 900 seconds. The maximum validity period of temporary access credentials is the maximum session duration specified for the current role. For more information, see Specify the maximum session duration for a RAM role.
You can use one of the following methods to obtain temporary access credentials:
Method 1
Call the AssumeRole operation.
Method 2
Use STS SDKs. For more information, see STS SDK overview.
Upload and download an object by using the temporary access credentials.
import com.aliyun.oss.*; import com.aliyun.oss.common.auth.*; import com.aliyun.oss.model.GetObjectRequest; import com.aliyun.oss.model.PutObjectRequest; import java.io.File; public class Demo { public static void main(String[] args) throws Throwable { // In this example, the endpoint of the China (Hangzhou) region is used. Specify your actual endpoint. String endpoint = "https://oss-cn-hangzhou.aliyuncs.com"; // Obtain temporary access credentials from the environment variables. Before you run the sample code, make sure that the OSS_ACCESS_KEY_ID, OSS_ACCESS_KEY_SECRET, and OSS_SESSION_TOKEN environment variables are configured. EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider(); // Specify the name of the bucket. Example: examplebucket. String bucketName = "examplebucket"; // Specify the full path of the object. Example: exampleobject.txt. Do not include the bucket name in the full path of the object. String objectName = "exampleobject.txt"; // Specify the full path of the local file. String pathName = "D:\\localpath\\examplefile.txt"; // After you obtain temporary access credentials from STS, you can use the access credentials to create an OSSClient instance. // Specify the region in which the bucket is located. For example, if the bucket is located in the China (Hangzhou) region, set the region to cn-hangzhou. String region = "cn-hangzhou"; // Create an OSSClient instance. ClientBuilderConfiguration clientBuilderConfiguration = new ClientBuilderConfiguration(); clientBuilderConfiguration.setSignatureVersion(SignVersion.V4); OSS ossClient = OSSClientBuilder.create() .endpoint(endpoint) .credentialsProvider(credentialsProvider) .clientConfiguration(clientBuilderConfiguration) .region(region) .build(); try { // Upload an object. In this example, a local file is uploaded to OSS. PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, objectName, new File(pathName)); ossClient.putObject(putObjectRequest); // Download an object to your local computer as a local file. If an existing file has the same name as the downloaded object, the existing file is overwritten by the downloaded object. Otherwise, the downloaded object is saved. //ossClient.getObject(new GetObjectRequest(bucketName, objectName), new File(pathName)); } 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(); } } } }
Use a signed URL to authorize temporary access
Usage notes
When you use an OSS SDK to generate a signed URL, the OSS SDK uses a specific algorithm based on the key information stored in the local computer to calculate a signature and adds the signature to a URL to ensure the validity and security of the URL. The operations performed to calculate and construct the URL are completed on the client. You do not need to send requests to the server over the network. This way, you do not need to grant specific permissions to the caller when you generate the signed URL. However, to allow third-party users to perform relevant operations on the resources authorized by the signed URL, you must make sure that the principal that calls the API operations to generate the signed URL has the corresponding permissions.
For example, if a principal wants to upload an object by using a signed URL, you must grant the oss:PutObject permission to the principal. If a principal wants to download or preview an object by using a signed URL, you must grant the oss:GetObject permission to the principal.
You can generate a signed URL and provide the URL to a visitor for temporary access. When you generate a signed URL, you can specify the validity period of the URL to limit the period of time during which the visitor can access specific data.
To generate a signed URL that is used to access resources over HTTPS, set the protocol in the endpoint to HTTPS.
The signed URL generated by using the following sample code may contain a plus sign (
+
). In this case, replace the plus sign (+
) in the URL with%2B
. Otherwise, the signed URL may not be used to access the object as expected.
The following sample code provides examples on how to generate signed URLs and use the signed URLs to upload and download objects.
Generate a signed URL that allows HTTP GET requests
The following sample code provides an example on how to generate a signed URL that allows HTTP GET requests:
import com.aliyun.oss.*;
import com.aliyun.oss.common.auth.*;
import java.net.URL;
import java.util.Date;
import java.util.Date;
public class Demo {
public static void main(String[] args) throws Throwable {
// In this example, the endpoint of the China (Hangzhou) region is used. Specify your actual endpoint.
String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
// 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.
EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();
// Specify the name of the bucket. Example: examplebucket.
String bucketName = "examplebucket";
// Specify the full path of the object. Example: exampleobject.txt. Do not include the bucket name in the full path of the object.
String objectName = "exampleobject.txt";
// Specify the region in which the bucket is located. For example, if the bucket is located in the China (Hangzhou) region, set the region to cn-hangzhou.
String region = "cn-hangzhou";
// Create an OSSClient instance.
ClientBuilderConfiguration clientBuilderConfiguration = new ClientBuilderConfiguration();
clientBuilderConfiguration.setSignatureVersion(SignVersion.V4);
OSS ossClient = OSSClientBuilder.create()
.endpoint(endpoint)
.credentialsProvider(credentialsProvider)
.clientConfiguration(clientBuilderConfiguration)
.region(region)
.build();
try {
// Specify the validity period of the signed URL. Unit: milliseconds. In this example, the validity period is set to 1 hour.
Date expiration = new Date(new Date().getTime() + 3600 * 1000L);
// Generate a signed URL that allows HTTP GET requests. Visitors can enter the URL in a browser to access specific OSS resources.
URL url = ossClient.generatePresignedUrl(bucketName, objectName, expiration);
System.out.println(url);
} 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();
}
}
}
}
Generate a signed URL that allows requests using other HTTP methods
To authorize users to temporarily perform operations, such as object upload and deletion, you must generate a signed URL that allows requests by using specific HTTP methods. For example, you can generate a signed URL that allows HTTP PUT requests to authorize users to upload objects.
The following sample code provides an example on how to generate a signed URL that allows other HTTP request methods:
import com.aliyun.oss.*;
import com.aliyun.oss.common.auth.*;
import com.aliyun.oss.common.utils.HttpHeaders;
import com.aliyun.oss.model.GeneratePresignedUrlRequest;
import java.io.ByteArrayInputStream;
import java.net.URL;
import java.util.*;
import java.util.Date;
import static com.aliyun.oss.internal.OSSHeaders.OSS_USER_METADATA_PREFIX;
public class Demo {
public static void main(String[] args) throws Throwable {
// In this example, the endpoint of the China (Hangzhou) region is used. Specify your actual endpoint.
String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
// 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.
EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();
// Specify the name of the bucket. Example: examplebucket.
String bucketName = "examplebucket";
// Specify the full path of the object. Example: exampleobject.txt. Do not include the bucket name in the full path of the object.
String objectName = "exampleobject.txt";
// Specify the region in which the bucket is located. For example, if the bucket is located in the China (Hangzhou) region, set the region to cn-hangzhou.
String region = "cn-hangzhou";
// Create an OSSClient instance.
ClientBuilderConfiguration clientBuilderConfiguration = new ClientBuilderConfiguration();
clientBuilderConfiguration.setSignatureVersion(SignVersion.V4);
OSS ossClient = OSSClientBuilder.create()
.endpoint(endpoint)
.credentialsProvider(credentialsProvider)
.clientConfiguration(clientBuilderConfiguration)
.region(region)
.build();
try {
GeneratePresignedUrlRequest request = new GeneratePresignedUrlRequest(bucketName, objectName, HttpMethod.PUT);
// Specify the validity period of the signed URL. Unit: milliseconds. In this example, the validity period is set to 1 hour.
Date expiration = new Date(new Date().getTime() + 3600 * 1000L);
request.setExpiration(expiration);
// Specify the content type.
request.setContentType("text/plain");
// Specify user metadata.
request.addUserMetadata("author", "aliy");
// Generate the signed URL.
URL signedUrl = ossClient.generatePresignedUrl(request);
System.out.println(signedUrl);
Map<String, String> requestHeaders = new HashMap<String, String>();
// Specify the content type. Make sure that the content type is the same as the content type that is specified when you generate the signed URL.
requestHeaders.put(HttpHeaders.CONTENT_TYPE, "text/plain");
// Specify user metadata.
requestHeaders.put(OSS_USER_METADATA_PREFIX + "author", "aliy");
// Use the signed URL to upload the object.
ossClient.putObject(signedUrl, new ByteArrayInputStream("Hello OSS".getBytes()), -1, requestHeaders, true);
} 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();
}
}
}
}
If you include the HttpMethod.PUT parameter when you create a signed URL, authorized visitors can use the signed URL to upload objects.
Generate a signed URL that includes specific parameters
Generate a signed URL that includes specific parameters
The following sample code provides an example on how to generate a signed URL that includes specific parameters:
import com.aliyun.oss.*; import com.aliyun.oss.common.auth.*; import com.aliyun.oss.model.GeneratePresignedUrlRequest; import java.net.URL; import java.util.*; import java.util.Date; public class Demo { public static void main(String[] args) throws Throwable { // In this example, the endpoint of the China (Hangzhou) region is used. Specify your actual endpoint. String endpoint = "https://oss-cn-hangzhou.aliyuncs.com"; // 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. EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider(); // Specify the name of the bucket. Example: examplebucket. String bucketName = "examplebucket"; // Specify the full path of the object. Example: exampleobject.txt. Do not include the bucket name in the full path of the object. String objectName = "exampleobject.txt"; // Specify the region in which the bucket is located. For example, if the bucket is located in the China (Hangzhou) region, set the region to cn-hangzhou. String region = "cn-hangzhou"; // Create an OSSClient instance. ClientBuilderConfiguration clientBuilderConfiguration = new ClientBuilderConfiguration(); clientBuilderConfiguration.setSignatureVersion(SignVersion.V4); OSS ossClient = OSSClientBuilder.create() .endpoint(endpoint) .credentialsProvider(credentialsProvider) .clientConfiguration(clientBuilderConfiguration) .region(region) .build(); try { // Create a request. GeneratePresignedUrlRequest generatePresignedUrlRequest = new GeneratePresignedUrlRequest(bucketName, objectName); // Set HttpMethod to PUT. generatePresignedUrlRequest.setMethod(HttpMethod.PUT); // Specify user metadata. generatePresignedUrlRequest.addUserMetadata("author", "baymax"); // Specify the content type. generatePresignedUrlRequest.setContentType("application/txt"); // Specify the validity period of the signed URL. Unit: milliseconds. In this example, the validity period is set to 1 hour. Date expiration = new Date(new Date().getTime() + 3600 * 1000L); generatePresignedUrlRequest.setExpiration(expiration); // Generate the signed URL. URL url = ossClient.generatePresignedUrl(generatePresignedUrlRequest); System.out.println(url); } 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(); } } } }
Generate a signed URL that includes the versionId parameter
The following sample code provides an example on how to generate a signed URL that includes the versionId parameter:
import com.aliyun.oss.*; import com.aliyun.oss.common.auth.*; import com.aliyun.oss.model.GeneratePresignedUrlRequest; import java.net.URL; import java.util.*; import java.util.Date; public class Demo { public static void main(String[] args) throws Throwable { // In this example, the endpoint of the China (Hangzhou) region is used. Specify your actual endpoint. String endpoint = "https://oss-cn-hangzhou.aliyuncs.com"; // 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. EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider(); // Specify the name of the bucket. Example: examplebucket. String bucketName = "examplebucket"; // Specify the full path of the object. Example: exampleobject.txt. Do not include the bucket name in the full path of the object. String objectName = "exampleobject.txt"; // Specify the version ID of the object. String versionId = "CAEQARiBgID8rumR2hYiIGUyOTAyZGY2MzU5MjQ5ZjlhYzQzZjNlYTAyZDE3****"; // Specify the region in which the bucket is located. For example, if the bucket is located in the China (Hangzhou) region, set the region to cn-hangzhou. String region = "cn-hangzhou"; // Create an OSSClient instance. ClientBuilderConfiguration clientBuilderConfiguration = new ClientBuilderConfiguration(); clientBuilderConfiguration.setSignatureVersion(SignVersion.V4); OSS ossClient = OSSClientBuilder.create() .endpoint(endpoint) .credentialsProvider(credentialsProvider) .clientConfiguration(clientBuilderConfiguration) .region(region) .build(); try { // Create a request. GeneratePresignedUrlRequest generatePresignedUrlRequest = new GeneratePresignedUrlRequest(bucketName, objectName); // Set HttpMethod to GET. generatePresignedUrlRequest.setMethod(HttpMethod.GET); // Specify the validity period of the signed URL. Unit: milliseconds. In this example, the validity period is set to 1 hour. Date expiration = new Date(new Date().getTime() + 3600 * 1000L); generatePresignedUrlRequest.setExpiration(expiration); // Specify the version ID of the object. Map<String, String> queryParam = new HashMap<String, String>(); queryParam.put("versionId", versionId); generatePresignedUrlRequest.setQueryParameter(queryParam); // Generate the signed URL. URL url = ossClient.generatePresignedUrl(generatePresignedUrlRequest); System.out.println(url); } 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(); } } } }
Use a signed URL to upload or download an object
Use a signed URL to upload an object by using simple upload
The following sample code provides an example on how to generate a signed URL and use the signed URL to upload an object by using simple upload:
NoteYou can also create a signed URL by using the signature tool in the OSS console and then use the signed URL to authorize users to upload an object by using simple upload. For more information about how to generate a signed URL, see URL Signature.
import com.aliyun.oss.*; import com.aliyun.oss.common.auth.*; import com.aliyun.oss.internal.OSSHeaders; import com.aliyun.oss.model.GeneratePresignedUrlRequest; import com.aliyun.oss.model.StorageClass; import org.apache.http.HttpEntity; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpPut; import org.apache.http.entity.FileEntity; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClients; import java.io.*; import java.net.URL; import java.util.*; import java.util.Date; public class Demo { public static void main(String[] args) throws Throwable { // In this example, the endpoint of the China (Hangzhou) region is used. Specify your actual endpoint. String endpoint = "https://oss-cn-hangzhou.aliyuncs.com"; // 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. EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider(); // Specify the name of the bucket. Example: examplebucket. String bucketName = "examplebucket"; // Specify the full path of the object. Example: exampleobject.txt. Do not include the bucket name in the full path of the object. String objectName = "exampleobject.txt"; // Specify the full path of the local file. By default, if you do not specify the full path of a local file, the local file is uploaded from the path of the project to which the sample program belongs. String pathName = "D:\\localpath\\examplefile.txt"; // Specify the region in which the bucket is located. For example, if the bucket is located in the China (Hangzhou) region, set the region to cn-hangzhou. String region = "cn-hangzhou"; // Create an OSSClient instance. ClientBuilderConfiguration clientBuilderConfiguration = new ClientBuilderConfiguration(); clientBuilderConfiguration.setSignatureVersion(SignVersion.V4); OSS ossClient = OSSClientBuilder.create() .endpoint(endpoint) .credentialsProvider(credentialsProvider) .clientConfiguration(clientBuilderConfiguration) .region(region) .build(); // Specify request headers. Map<String, String> headers = new HashMap<String, String>(); /*// Specify the storage class of the object. headers.put(OSSHeaders.STORAGE_CLASS, StorageClass.Standard.toString()); // Specify the content type. headers.put(OSSHeaders.CONTENT_TYPE, "text/txt");*/ // Specify user metadata. Map<String, String> userMetadata = new HashMap<String, String>(); /*userMetadata.put("key1","value1"); userMetadata.put("key2","value2");*/ URL signedUrl = null; try { // Specify the validity period of the signed URL. Unit: milliseconds. In this example, the validity period is set to 1 hour. Date expiration = new Date(new Date().getTime() + 3600 * 1000L); // Generate the signed URL. GeneratePresignedUrlRequest request = new GeneratePresignedUrlRequest(bucketName, objectName, HttpMethod.PUT); // Specify the validity period of the signed URL. request.setExpiration(expiration); // Add headers to the request. request.setHeaders(headers); // Specify user metadata. request.setUserMetadata(userMetadata); // Generate a signed URL that allows HTTP PUT requests. signedUrl = ossClient.generatePresignedUrl(request); // Display the signed URL. System.out.println("signed url for putObject: " + signedUrl); } 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()); } // Use the signed URL to authorize users to upload the object. In this example, HttpClients is used. putObjectWithHttp(signedUrl, pathName, headers, userMetadata); } public static void putObjectWithHttp(URL signedUrl, String pathName, Map<String, String> headers, Map<String, String> userMetadata) throws IOException { CloseableHttpClient httpClient = null; CloseableHttpResponse response = null; try { HttpPut put = new HttpPut(signedUrl.toString()); HttpEntity entity = new FileEntity(new File(pathName)); put.setEntity(entity); // If you configure headers, such as the user metadata and storage class headers, when a signed URL is generated, these headers must be sent to the server when the signed URL is used to upload the local file. If the headers that are sent to the server for the signature calculation are different from the headers specified when the signed URL is generated, a signature error is reported. for(Map.Entry header: headers.entrySet()){ put.addHeader(header.getKey().toString(),header.getValue().toString()); } for(Map.Entry meta: userMetadata.entrySet()){ // If userMeta is used, the x-oss-meta- prefix is added to userMeta. If you use other methods to generate a signed URL, the x-oss-meta- prefix is also added to userMeta. put.addHeader("x-oss-meta-"+meta.getKey().toString(), meta.getValue().toString()); } httpClient = HttpClients.createDefault(); response = httpClient.execute(put); System.out.println("Upload status code:"+response.getStatusLine().getStatusCode()); if(response.getStatusLine().getStatusCode() == 200){ System.out.println("The object is uploaded by using the network library."); } System.out.println(response.toString()); } catch (Exception e){ e.printStackTrace(); } finally { response.close(); httpClient.close(); } } }
Use signed URLs to upload an object by using multipart upload
If you want to use signed URLs to authorize third-party applications to upload a large object by using multipart upload, you must initiate a multipart upload task, generate a signed URL for each part, and then provide the third-party applications with the signed URLs. This way, the third-party users can use the signed URLs to upload all parts of the object and combine the parts into a complete object.
The following sample code provides an example on how to generate signed URLs and use the signed URLs to upload an object by using multipart upload:
import com.aliyun.oss.*; import com.aliyun.oss.common.auth.*; import com.aliyun.oss.common.comm.io.BoundedInputStream; import com.aliyun.oss.common.utils.BinaryUtil; import com.aliyun.oss.common.utils.CRC64; import com.aliyun.oss.internal.OSSHeaders; import com.aliyun.oss.model.*; import org.apache.commons.codec.digest.DigestUtils; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpPut; import org.apache.http.entity.BufferedHttpEntity; import org.apache.http.entity.InputStreamEntity; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.DefaultHttpRequestRetryHandler; import org.apache.http.impl.client.HttpClients; import java.io.*; import java.math.BigInteger; import java.net.URL; import java.util.*; import java.util.Date; import java.util.zip.CheckedInputStream; public class SignUrlMultipart { public static void main(String[] args) throws Throwable { // In this example, the endpoint of the China (Hangzhou) region is used. Specify your actual endpoint. String endpoint = "https://oss-cn-hangzhou.aliyuncs.com"; // 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. EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider(); // Specify the name of the bucket. Example: examplebucket. String bucketName = "examplebucket"; // Specify the full path of the object. Example: exampleobject.txt. Do not include the bucket name in the full path of the object. String objectName = "exampleobject.txt"; // Specify the full path of the local file. By default, if you do not specify the full path of a local file, the local file is uploaded from the path of the project to which the sample program belongs. String pathName = "D:\\localpath\\examplefile.txt"; // Specify the validity period of the signed URL. Unit: milliseconds. In this example, the validity period is set to 1 hour. long expireTime = 3600*1000L; // Specify the region in which the bucket is located. For example, if the bucket is located in the China (Hangzhou) region, set the region to cn-hangzhou. String region = "cn-hangzhou"; // Create an OSSClient instance. ClientBuilderConfiguration clientBuilderConfiguration = new ClientBuilderConfiguration(); clientBuilderConfiguration.setSignatureVersion(SignVersion.V4); OSS ossClient = OSSClientBuilder.create() .endpoint(endpoint) .credentialsProvider(credentialsProvider) .clientConfiguration(clientBuilderConfiguration) .region(region) .build(); // Create an InitiateMultipartUploadRequest object. InitiateMultipartUploadRequest initRequest = new InitiateMultipartUploadRequest(bucketName, objectName); // Initiate the multipart upload task. InitiateMultipartUploadResult upResult = ossClient.initiateMultipartUpload(initRequest); // Obtain the upload ID. The upload ID is the unique identifier of the multipart upload task. You can use the upload ID to perform related operations, such as canceling and querying the multipart upload task. String uploadId = upResult.getUploadId(); // partETags is a set of PartETags. A PartETag consists of the part number and ETag of a part. List<PartETag> partETags = new ArrayList<PartETag>(); // Specify the part size, which is used to calculate the number of parts of the object. Unit: bytes. long partSize = 1 * 100 * 1024L; // In this example, the part size is set to 100 KB. // Specify the full path of the local file. By default, if you do not specify the full path of a local file, the local file is uploaded from the path of the project to which the sample program belongs. File sampleFile = new File(pathName); long fileLength = sampleFile.length(); // If you want to upload the local file as only one part, set the part size to the local file size. // long fileLength = sampleFile.length(); int partCount = (int) (fileLength / partSize); if (fileLength % partSize != 0) { partCount++; } // Specify request headers for the signed URLs. Map<String, String> headers = new HashMap<String, String>(); /*// Specify the storage class of the object. headers.put(OSSHeaders.STORAGE_CLASS, StorageClass.Standard.toString()); // Specify the content type. headers.put(OSSHeaders.CONTENT_TYPE, "text/txt");*/ // Traverse all parts to obtain all signed URLs and upload the parts. // You can also obtain the signed URLs of all parts at a time and then upload the parts. The following sample code provides an example on how to obtain a single signed URL and use the signed URL to upload a part: for (int i = 0; i < partCount; i++) { long startPos = i * partSize; long curPartSize = (i + 1 == partCount) ? (fileLength - startPos) : partSize; /*// Configure MD5 verification. You can perform MD5 verification only for a single part. FileInputStream inStream = new FileInputStream(pathName); // Skip the parts that are uploaded. inStream.skip(startPos); BoundedInputStream entity = new BoundedInputStream(inStream, partSize); String md5 = BinaryUtil.toBase64String(DigestUtils.md5(entity)); headers.put("Content-MD5", md5);*/ String signUrl = getSignUrl(ossClient, bucketName, objectName, HttpMethod.PUT, expireTime, i + 1, uploadId, headers); // Use the signed URL to upload the part. In this example, HttpClients is used. putObjectWithHttp(signUrl, pathName, startPos, curPartSize, headers); } // If the system for part upload is different from the system for part combination, you must list parts before you can combine the parts. // List the uploaded parts. ListPartsRequest listPartsRequest = new ListPartsRequest(bucketName, objectName, uploadId); PartListing partListing = ossClient.listParts(listPartsRequest); // Traverse the parts and populate partETags. for (PartSummary part : partListing.getParts()) { PartETag partETag = new PartETag(part.getPartNumber(), part.getETag()); partETags.add(partETag); } // Combine the parts. CompleteMultipartUploadRequest completeMultipartUploadRequest = new CompleteMultipartUploadRequest(bucketName, objectName, uploadId, partETags); // String md5 = BinaryUtil.toBase64String(BinaryUtil.calculateMd5("aaa".getBytes())); // Specify that an existing object that has the same name is not overwritten. // completeMultipartUploadRequest.addHeader("x-oss-forbid-overwrite", "true"); // Complete the multipart upload task. CompleteMultipartUploadResult completeMultipartUploadResult = ossClient.completeMultipartUpload(completeMultipartUploadRequest); System.out.println("Parts are combined. The upload task is complete."); // Check whether the uploaded file is complete. CRC64 crc = new CRC64(); InputStream inStream = new FileInputStream(pathName); byte[] bytes = new byte[1024]; int cnt; while ((cnt = inStream.read(bytes)) != -1) { crc.update(bytes, 0, cnt); } if(crc.getValue() == completeMultipartUploadResult.getServerCRC()){ System.out.println("File upload is complete"); } else { System.out.println("The uploaded file is incomplete.Handle the exception"); } } public static void putObjectWithHttp(String signedUrl, String pathName, long startPos, long partSize, Map<String, String> headers) throws IOException { CloseableHttpClient httpClient = null; CloseableHttpResponse response = null; try { HttpPut put = new HttpPut(signedUrl); FileInputStream inStream = new FileInputStream(pathName); // Skip the parts that are uploaded. inStream.skip(startPos); InputStreamEntity entity = new InputStreamEntity(inStream, partSize); BufferedHttpEntity byteArrayEntity = new BufferedHttpEntity(entity); put.setEntity(byteArrayEntity); // If you configure headers, such as the user metadata and storage class headers, when a signed URL is generated, these headers must be sent to the server when the signed URL is used to upload the local file. If the headers that are sent to the server for the signature calculation are different from the headers specified when the signed URL is generated, a signature error is reported. for(Map.Entry header: headers.entrySet()){ put.addHeader(header.getKey().toString(),header.getValue().toString()); } // Set the number of retries when a request error occurs to 3. The following sample code is used an example to describe how to specify the number of retries when a request error occurs. Specify the number of retries when a request error occurs based on your business requirements. httpClient = HttpClients.custom().setRetryHandler(new DefaultHttpRequestRetryHandler(3, true)).build(); response = httpClient.execute(put); System.out.println("Upload status code:"+response.getStatusLine().getStatusCode()); if(response.getStatusLine().getStatusCode() == 200){ System.out.println("The object is uploaded by using the library."); } System.out.println(response.toString()); } catch (Exception e){ e.printStackTrace(); } finally { if(response != null){ response.close(); } if(httpClient != null){ httpClient.close(); } } } public static String getSignUrl(OSS ossClient, String bucketName, String objectName, HttpMethod method, long expireTime, int partNum, String uploadId, Map<String, String> headers){ // Specify the validity period of the signed URL. Unit: milliseconds. Date expiration = new Date(new Date().getTime() + expireTime); // Generate the signed URL. GeneratePresignedUrlRequest request = new GeneratePresignedUrlRequest(bucketName, objectName, method); // Specify the validity period of the signed URL. request.setExpiration(expiration); // Add headers to the request. request.setHeaders(headers); request.addQueryParameter("partNumber", String.valueOf(partNum)); request.addQueryParameter("uploadId", uploadId); // Generate the signed URL that allows HTTP requests. URL signedUrl = ossClient.generatePresignedUrl(request); // Display the signed URL. System.out.println("signed url: " + signedUrl); return signedUrl.toString(); } }
Use a signed URL to download an object
The following sample code provides an example on how to use a signed URL to download an object:
import com.aliyun.oss.*; import com.aliyun.oss.common.auth.*; import com.aliyun.oss.internal.OSSHeaders; import com.aliyun.oss.model.GeneratePresignedUrlRequest; import com.aliyun.oss.model.StorageClass; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpGet; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClients; import java.io.*; import java.net.URL; import java.util.*; import java.util.Date; public class Demo { public static void main(String[] args) throws Throwable { // In this example, the endpoint of the China (Hangzhou) region is used. Specify your actual endpoint. String endpoint = "https://oss-cn-hangzhou.aliyuncs.com"; // 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. EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider(); // Specify the name of the bucket. Example: examplebucket. String bucketName = "examplebucket"; // Specify the full path of the object. Example: exampleobject.txt. Do not include the bucket name in the full path of the object. String objectName = "exampleobject.txt"; // Specify the local path to which you want to download the object. String pathName = "D:\\localpath\\examplefile.txt"; // Specify the region in which the bucket is located. For example, if the bucket is located in the China (Hangzhou) region, set the region to cn-hangzhou. String region = "cn-hangzhou"; // Create an OSSClient instance. ClientBuilderConfiguration clientBuilderConfiguration = new ClientBuilderConfiguration(); clientBuilderConfiguration.setSignatureVersion(SignVersion.V4); OSS ossClient = OSSClientBuilder.create() .endpoint(endpoint) .credentialsProvider(credentialsProvider) .clientConfiguration(clientBuilderConfiguration) .region(region) .build(); // Specify request headers. Map<String, String> headers = new HashMap<String, String>(); /*// Specify the storage class of the object. headers.put(OSSHeaders.STORAGE_CLASS, StorageClass.Standard.toString()); // Specify the content type. headers.put(OSSHeaders.CONTENT_TYPE, "text/txt");*/ // Specify user metadata. Map<String, String> userMetadata = new HashMap<String, String>(); /*userMetadata.put("key1","value1"); userMetadata.put("key2","value2");*/ URL signedUrl = null; try { // Specify the validity period of the signed URL. Unit: milliseconds. In this example, the validity period is set to 1 hour. Date expiration = new Date(new Date().getTime() + 3600 * 1000L); // Generate the signed URL. GeneratePresignedUrlRequest request = new GeneratePresignedUrlRequest(bucketName, objectName, HttpMethod.GET); // Specify the validity period of the signed URL. request.setExpiration(expiration); // Add headers to the request. request.setHeaders(headers); // Specify user metadata. request.setUserMetadata(userMetadata); // Specify query parameters. // Map<String, String> queryParam = new HashMap<String, String>(); // Specify the IP address or CIDR block, which is the value of the sourceIpFromSource field in the log. // queryParam.put("x-oss-ac-source-ip","192.0.2.0"); // Convert the subnet mask to binary and then enter the number of 1s in the result. // queryParam.put("x-oss-ac-subnet-mask","32"); // Specify the ID of the virtual private cloud (VPC). // queryParam.put("x-oss-ac-vpc-id","vpc-12345678"); // Specify whether the request can be forwarded. // queryParam.put("x-oss-ac-forward-allow","true"); // request.setQueryParameter(queryParam); // Configure single-connection bandwidth throttling, such as 100 KB/s. Unit: bit/s. // request.setTrafficLimit(100 * 1024 * 8); // Generate a signed URL that allows HTTP GET requests. signedUrl = ossClient.generatePresignedUrl(request); // Display the signed URL. System.out.println("signed url for putObject: " + signedUrl); } 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()); } // Use the signed URL to download an object. In this example, HttpClients is used. getObjectWithHttp(signedUrl, pathName, headers, userMetadata); } public static void getObjectWithHttp(URL signedUrl, String pathName, Map<String, String> headers, Map<String, String> userMetadata) throws IOException { CloseableHttpClient httpClient = null; CloseableHttpResponse response = null; try { HttpGet get = new HttpGet(signedUrl.toString()); // If you configure headers, such as user metadata and storage class, when a signed URL is generated, you must send these parameters to the server when you call the signed URL to download the object. If the headers that are sent to the server for the signature calculation are different from the headers specified when the signed URL is generated, a signature error is reported. for(Map.Entry header: headers.entrySet()){ get.addHeader(header.getKey().toString(),header.getValue().toString()); } for(Map.Entry meta: userMetadata.entrySet()){ // If userMeta is used, the x-oss-meta- prefix is added to userMeta. When you use other methods to generate a signed URL for object download, the x-oss-meta- prefix is also added to userMeta. get.addHeader("x-oss-meta-"+meta.getKey().toString(), meta.getValue().toString()); } httpClient = HttpClients.createDefault(); response = httpClient.execute(get); System.out.println("Download status code:"+response.getStatusLine().getStatusCode()); if(response.getStatusLine().getStatusCode() == 200){ System.out.println("The object is downloaded by using the network library"); } System.out.println(response.toString()); // Save the object to the disk. saveFileToLocally(response.getEntity().getContent(), pathName); } catch (Exception e){ e.printStackTrace(); } finally { response.close(); httpClient.close(); } } public static void saveFileToLocally(InputStream inputStream, String pathName) throws IOException { DataInputStream in = null; OutputStream out = null; try { in = new DataInputStream(inputStream); out = new DataOutputStream(new FileOutputStream(pathName)); int bytes = 0; byte[] bufferOut = new byte[1024]; while ((bytes = in.read(bufferOut)) != -1) { out.write(bufferOut, 0, bytes); } } catch (Exception e){ e.printStackTrace(); } finally { in.close(); out.close(); } } }
FAQ
When I use a signed URL to upload a local file, is the file uploaded if the signed URL expires during the upload?
When you use simple upload, the file is still uploaded even if the signed URL expires during the upload.
When you use multipart upload, the remaining parts may not be uploaded if the signed URLs of parts expire during the upload.