Par défaut, la liste de contrôle d'accès (ACL) d'un objet dans un compartiment Object Storage Service (OSS) est privée. Seul le propriétaire de l'objet est autorisé à y accéder. Cette rubrique explique comment utiliser le SDK OSS pour Go afin de générer une URL pré-signée permettant à un utilisateur de télécharger temporairement l'objet via une requête HTTP GET. L'URL reste valide pendant une période définie, durant laquelle l'utilisateur peut télécharger l'objet plusieurs fois. Une fois l'URL expirée, l'utilisateur doit obtenir une nouvelle URL pré-signée.
Notes
Le code exemple de cette rubrique utilise l'ID de région
cn-hangzhoupour la région Chine (Hangzhou). Par défaut, un endpoint public est utilisé pour accéder aux ressources du compartiment. Si vous accédez aux ressources du compartiment depuis d'autres services Alibaba Cloud situés dans la même région, utilisez un endpoint interne. Pour plus d'informations sur les régions et les endpoints OSS, consultez la page Regions and endpoints.Dans cette rubrique, les identifiants d'accès sont récupérés à partir des variables d'environnement. Pour savoir comment configurer les identifiants d'accès, consultez la section Configure access credentials.
Aucune autorisation n'est requise pour générer une URL pré-signée. Toutefois, pour qu'un tiers puisse télécharger l'objet à l'aide de cette URL, l'utilisateur qui la génère doit disposer de l'autorisation
oss:GetObject. Pour plus d'informations sur l'attribution des autorisations, consultez la page Grant custom permissions to a RAM user.Cette rubrique utilise des URL pré-signées V4. La durée de validité maximale de ces URL est de sept jours. Pour plus d'informations, consultez la section (Recommended) Include a V4 signature in a URL.
Procédure
La procédure suivante décrit comment télécharger un objet à l'aide d'une URL pré-signée :
Définition de la méthode
Appelez une opération spécifique pour générer une URL pré-signée accordant des autorisations d'accès temporaires aux objets d'un compartiment. L'URL pré-signée peut être utilisée plusieurs fois avant son expiration.
Le code suivant présente la syntaxe de l'opération presign :
func (c *Client) Presign(ctx context.Context, request any, optFns ...func(*PresignOptions)) (result *PresignResult, err error)
Paramètres de requête
|
Paramètre |
Type |
Description |
|
ctx |
context.Context |
Contexte de la requête. |
|
request |
*GetObjectRequest |
Nom de l'opération API utilisée pour générer une URL pré-signée. |
|
optFns |
...func(*PresignOptions) |
Durée de validité de l'URL pré-signée. Si vous ne spécifiez pas ce paramètre, la valeur par défaut de 15 minutes s'applique. Ce paramètre est facultatif. |
Le tableau suivant décrit les options de PresignOptions.
|
Option |
Type |
Description |
|
Expires |
time.Duration |
Durée de validité de l'URL pré-signée. Par exemple, pour définir une validité de 30 minutes, attribuez la valeur |
|
Expiration |
time.Time |
Date et heure d'expiration absolue de l'URL pré-signée. |
Si vous utilisez l'algorithme de signature V4, la durée de validité peut atteindre sept jours. Si vous spécifiez à la fois Expiration et Expires, le paramètre Expiration est prioritaire.
Paramètres de réponse
|
Propriété de réponse |
Type |
Description |
|
result |
*PresignResult |
Résultats renvoyés, incluant l'URL pré-signée, la méthode HTTP, la durée de validité et les en-têtes de requête spécifiés dans la demande. |
|
err |
error |
État de la requête. En cas d'échec, la valeur de err n'est pas nil. |
Le tableau suivant décrit les paramètres de réponse de PresignResult.
|
Paramètre |
Type |
Description |
|
Method |
string |
Méthode HTTP correspondant à l'opération. Par exemple, la méthode HTTP de l'opération GetObject est GET. |
|
URL |
string |
URL pré-signée. |
|
Expiration |
time.Time |
Date et heure d'expiration de l'URL pré-signée. |
|
SignedHeaders |
map[string]string |
En-têtes de requête spécifiés dans la demande. Par exemple, si la valeur de l'en-tête Content-Type est définie, les informations relatives à Content-Type sont renvoyées. |
Exemple de code
-
L'exemple de code suivant montre comment un propriétaire d'objet peut générer une URL pré-signée autorisant les requêtes HTTP GET :
package main import ( "context" "flag" "log" "time" "github.com/aliyun/alibabacloud-oss-go-sdk-v2/oss" "github.com/aliyun/alibabacloud-oss-go-sdk-v2/oss/credentials" ) // Define global variables. var ( region string // The region in which the bucket is located. bucketName string // The name of the bucket. objectName string // The name of the object. ) // The init function is used to initialize command-line parameters. func init() { flag.StringVar(®ion, "region", "", "The region in which the bucket is located.") flag.StringVar(&bucketName, "bucket", "", "The name of the bucket.") flag.StringVar(&objectName, "object", "", "The name of the object.") } func main() { // Parse command-line parameters. flag.Parse() // Check whether the bucket name is empty. if len(bucketName) == 0 { flag.PrintDefaults() log.Fatalf("invalid parameters, bucket name required") } // Check whether the region is empty. if len(region) == 0 { flag.PrintDefaults() log.Fatalf("invalid parameters, region required") } // Check whether the object name is empty. if len(objectName) == 0 { flag.PrintDefaults() log.Fatalf("invalid parameters, object name required") } // Load the default configurations and specify the credential provider and region. cfg := oss.LoadDefaultConfig(). WithCredentialsProvider(credentials.NewEnvironmentVariableCredentialsProvider()). WithRegion(region) // Create an OSS client. client := oss.NewClient(cfg) // Generate a presigned URL for the GetObject request. result, err := client.Presign(context.TODO(), &oss.GetObjectRequest{ Bucket: oss.Ptr(bucketName), Key: oss.Ptr(objectName), }, oss.PresignExpires(10*time.Minute), ) if err != nil { log.Fatalf("failed to get object presign %v", err) } log.Printf("request method:%v\n", result.Method) log.Printf("request expiration:%v\n", result.Expiration) log.Printf("request url:%v\n", result.URL) if len(result.SignedHeaders) > 0 { // If the returned result contains signed headers, you must include the corresponding request headers when you send a GET request using the presigned URL. Otherwise, the request may fail or a signature error may occur. log.Printf("signed headers:\n") for k, v := range result.SignedHeaders { log.Printf("%v: %v\n", k, v) } } } -
Les autres utilisateurs peuvent télécharger le fichier à l'aide de l'URL pré-signée pour les requêtes GET.
curl
curl -SO "https://examplebucket.oss-cn-hangzhou.aliyuncs.com/exampleobject.txt?x-oss-date=20241112T092756Z&x-oss-expires=3599&x-oss-signature-version=OSS4-HMAC-SHA256&x-oss-credential=LTAI****************/20241112/cn-hangzhou/oss/aliyun_v4_request&x-oss-signature=ed5a******************************************************"Java
import java.io.BufferedInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.net.HttpURLConnection; import java.net.URL; public class Demo { public static void main(String[] args) { // Replace with the generated presigned URL for the GET request. String fileURL = "https://examplebucket.oss-cn-hangzhou.aliyuncs.com/exampleobject.txt?x-oss-date=20241112T092756Z&x-oss-expires=3599&x-oss-signature-version=OSS4-HMAC-SHA256&x-oss-credential=LTAI****************/20241112/cn-hangzhou/oss/aliyun_v4_request&x-oss-signature=ed5a******************************************************"; // Enter the destination path to save the file, including the file name and extension. String savePath = "C:/downloads/myfile.txt"; try { downloadFile(fileURL, savePath); System.out.println("Download completed!"); } catch (IOException e) { System.err.println("Error during download: " + e.getMessage()); } } private static void downloadFile(String fileURL, String savePath) throws IOException { URL url = new URL(fileURL); HttpURLConnection httpConn = (HttpURLConnection) url.openConnection(); httpConn.setRequestMethod("GET"); // Check the response code. int responseCode = httpConn.getResponseCode(); if (responseCode == HttpURLConnection.HTTP_OK) { // Input stream. InputStream inputStream = new BufferedInputStream(httpConn.getInputStream()); // Output stream. FileOutputStream outputStream = new FileOutputStream(savePath); byte[] buffer = new byte[4096]; // Buffer. int bytesRead; while ((bytesRead = inputStream.read(buffer)) != -1) { outputStream.write(buffer, 0, bytesRead); } outputStream.close(); inputStream.close(); } else { System.out.println("No file to download. Server replied HTTP code: " + responseCode); } httpConn.disconnect(); } }Node.js
const https = require('https'); const fs = require('fs'); const fileURL = "https://examplebucket.oss-cn-hangzhou.aliyuncs.com/exampleobject.txt?x-oss-date=20241112T092756Z&x-oss-expires=3599&x-oss-signature-version=OSS4-HMAC-SHA256&x-oss-credential=LTAI****************/20241112/cn-hangzhou/oss/aliyun_v4_request&x-oss-signature=ed5a******************************************************"; const savePath = "C:/downloads/myfile.txt"; https.get(fileURL, (response) => { if (response.statusCode === 200) { const fileStream = fs.createWriteStream(savePath); response.pipe(fileStream); fileStream.on('finish', () => { fileStream.close(); console.log("Download completed!"); }); } else { console.error(`Download failed. Server responded with code: ${response.statusCode}`); } }).on('error', (err) => { console.error("Error during download:", err.message); });Python
import requests file_url = "https://examplebucket.oss-cn-hangzhou.aliyuncs.com/exampleobject.txt?x-oss-date=20241112T092756Z&x-oss-expires=3599&x-oss-signature-version=OSS4-HMAC-SHA256&x-oss-credential=LTAI****************/20241112/cn-hangzhou/oss/aliyun_v4_request&x-oss-signature=ed5a******************************************************" save_path = "C:/downloads/myfile.txt" try: response = requests.get(file_url, stream=True) if response.status_code == 200: with open(save_path, 'wb') as f: for chunk in response.iter_content(4096): f.write(chunk) print("Download completed!") else: print(f"No file to download. Server replied HTTP code: {response.status_code}") except Exception as e: print("Error during download:", e)Go
package main import ( "io" "net/http" "os" ) func main() { fileURL := "https://examplebucket.oss-cn-hangzhou.aliyuncs.com/exampleobject.txt?x-oss-date=20241112T092756Z&x-oss-expires=3599&x-oss-signature-version=OSS4-HMAC-SHA256&x-oss-credential=LTAI****************/20241112/cn-hangzhou/oss/aliyun_v4_request&x-oss-signature=ed5a******************************************************" savePath := "C:/downloads/myfile.txt" response, err := http.Get(fileURL) if err != nil { panic(err) } defer response.Body.Close() if response.StatusCode == http.StatusOK { outFile, err := os.Create(savePath) if err != nil { panic(err) } defer outFile.Close() _, err = io.Copy(outFile, response.Body) if err != nil { panic(err) } println("Download completed!") } else { println("No file to download. Server replied HTTP code:", response.StatusCode) } }JavaScript
const fileURL = "https://examplebucket.oss-cn-hangzhou.aliyuncs.com/exampleobject.txt?x-oss-date=20241112T092756Z&x-oss-expires=3599&x-oss-signature-version=OSS4-HMAC-SHA256&x-oss-credential=LTAI****************/20241112/cn-hangzhou/oss/aliyun_v4_request&x-oss-signature=ed5a******************************************************"; const savePath = "C:/downloads/myfile.txt"; // The file name to use for the download. fetch(fileURL) .then(response => { if (!response.ok) { throw new Error(`Server replied HTTP code: ${response.status}`); } return response.blob(); // Convert the response to a blob. }) .then(blob => { const link = document.createElement('a'); link.href = window.URL.createObjectURL(blob); link.download = savePath; // Set the name of the downloaded file. document.body.appendChild(link); // This step ensures that the link exists in the document. link.click(); // Simulate a click on the download link. link.remove(); // Remove the link after completion. console.log("Download completed!"); }) .catch(error => { console.error("Error during download:", error); });Android-Java
import android.os.AsyncTask; import android.os.Environment; import java.io.BufferedInputStream; import java.io.FileOutputStream; import java.io.InputStream; import java.net.HttpURLConnection; import java.net.URL; public class DownloadTask extends AsyncTask<String, String, String> { @Override protected String doInBackground(String... params) { String fileURL = params[0]; String savePath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS) + "/myfile.txt"; // The modified save path. try { URL url = new URL(fileURL); HttpURLConnection httpConn = (HttpURLConnection) url.openConnection(); httpConn.setRequestMethod("GET"); int responseCode = httpConn.getResponseCode(); if (responseCode == HttpURLConnection.HTTP_OK) { InputStream inputStream = new BufferedInputStream(httpConn.getInputStream()); FileOutputStream outputStream = new FileOutputStream(savePath); byte[] buffer = new byte[4096]; int bytesRead; while ((bytesRead = inputStream.read(buffer)) != -1) { outputStream.write(buffer, 0, bytesRead); } outputStream.close(); inputStream.close(); return "Download completed!"; } else { return "No file to download. Server replied HTTP code: " + responseCode; } } catch (Exception e) { return "Error during download: " + e.getMessage(); } } }Objective-C
#import <Foundation/Foundation.h> int main(int argc, const char * argv[]) { @autoreleasepool { // Define the file URL and save path (change to a valid path). NSString *fileURL = @"https://examplebucket.oss-cn-hangzhou.aliyuncs.com/exampleobject.txt?x-oss-date=20241112T092756Z&x-oss-expires=3599&x-oss-signature-version=OSS4-HMAC-SHA256&x-oss-credential=LTAI****************/20241112/cn-hangzhou/oss/aliyun_v4_request&x-oss-signature=ed5a******************************************************"; NSString *savePath = @"/Users/your_username/Desktop/myfile.txt"; // Replace with your username. // Create a URL object. NSURL *url = [NSURL URLWithString:fileURL]; // Create a download task. NSURLSessionDataTask *task = [[NSURLSession sharedSession] dataTaskWithURL:url completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { // Error handling. if (error) { NSLog(@"Error during download: %@", error.localizedDescription); return; } // Check the data. if (!data) { NSLog(@"No data received."); return; } // Save the file. NSError *writeError = nil; BOOL success = [data writeToURL:[NSURL fileURLWithPath:savePath] options:NSDataWritingAtomic error:&writeError]; if (success) { NSLog(@"Download completed!"); } else { NSLog(@"Error saving file: %@", writeError.localizedDescription); } }]; // Start the task. [task resume]; // Keep the main thread running so that the asynchronous request can be completed. [[NSRunLoop currentRunLoop] run]; } return 0; }
Scénarios courants
Générer une URL pré-signée autorisant les requêtes HTTP GET pour une version spécifique d'un objet
Utiliser une URL pré-signée contenant des en-têtes de requête spécifiques pour télécharger un objet
Forcer le téléchargement d'un objet à l'aide d'une URL pré-signée
Générer une URL pré-signée à l'aide d'un nom de domaine personnalisé
Références
Pour consulter l'exemple de code complet utilisé pour télécharger un objet à l'aide d'une URL pré-signée, rendez-vous sur la page GitHub example.
Pour plus d'informations sur l'opération API permettant de télécharger un objet via une URL pré-signée, consultez la documentation Presign.