Par défaut, les objets stockés dans un compartiment Object Storage Service (OSS) sont privés et seul le propriétaire de l'objet peut y accéder. Cette rubrique explique comment utiliser le SDK PHP OSS pour générer une URL signée destinée à une requête GET. L'URL signée reste valide pendant une période définie et permet à d'autres utilisateurs de télécharger temporairement l'objet. Vous pouvez utiliser l'URL plusieurs fois avant son expiration. Une fois l'URL expirée, vous devez en générer une nouvelle.
Notes
Le code exemple fourni dans cette rubrique utilise l'ID de la région Chine (Hangzhou),
cn-hangzhou, à titre d'exemple. Par défaut, il utilise un endpoint public. Si vous souhaitez accéder à OSS 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 pris en charge par OSS, consultez la section Regions and endpoints.Cette rubrique illustre l'utilisation de variables d'environnement pour obtenir les identifiants d'accès. Pour découvrir d'autres méthodes de configuration des identifiants d'accès, reportez-vous à la section Configure access credentials for PHP.
Aucune autorisation spécifique n'est requise pour générer une URL signée. Toutefois, un tiers ne pourra télécharger l'objet avec succès via l'URL signée que si vous disposez de l'autorisation
oss:GetObject. Pour savoir comment accorder des autorisations, consultez la section Grant custom access policies to a RAM user.L'exemple de code présenté ici utilise une URL signée V4, dont la durée de validité maximale est de 7 jours. Pour en savoir plus, consultez la section Signature V4 (recommended).
Procédure
La procédure suivante décrit comment télécharger un objet à l'aide d'une URL pré-signée :
Paramètres
|
Paramètre |
Obligatoire |
Description |
Exemple |
|
|
Oui |
Région dans laquelle se trouve le compartiment. |
|
|
|
Oui |
Nom du compartiment. |
|
|
|
Oui |
Nom de l'objet, incluant le chemin d'accès. |
|
|
|
Non |
Durée d'expiration en secondes. Valeur par défaut : 900. |
|
|
|
Non |
Endpoint. Si aucun endpoint n'est spécifié, le système utilise automatiquement l'endpoint public correspondant en fonction de la région. |
|
Exemple de code
-
Le propriétaire de l'objet génère une URL signée pour une requête GET.
<?php // Import the autoloader file to ensure that dependency libraries are loaded correctly. require_once __DIR__ . '/../../vendor/autoload.php'; use AlibabaCloud\Oss\V2 as Oss; // Define the description for command-line arguments. $optsdesc = [ "region" => ['help' => 'The region in which the bucket is located.', 'required' => True], // The region where the bucket is located. (Required) "endpoint" => ['help' => 'The domain names that other services can use to access OSS.', 'required' => False], // The endpoint to access OSS. (Optional) "bucket" => ['help' => 'The name of the bucket', 'required' => True], // The bucket name. (Required) "key" => ['help' => 'The name of the object', 'required' => True], // The object name. (Required) "expire" => ['help' => 'The expiration time in seconds (default: 900)', 'required' => False], // The expiration time in seconds. (Optional, default: 900) ]; // Convert the argument descriptions to the long options format required by getopt. // A colon ":" after each argument indicates that it requires a value. $longopts = \array_map(function ($key) { return "$key:"; }, array_keys($optsdesc)); // Parse the command-line arguments. $options = getopt("", $longopts); // Check if all required arguments are provided. foreach ($optsdesc as $key => $value) { if ($value['required'] === True && empty($options[$key])) { $help = $value['help']; // Get the help information for the argument. echo "Error: the following arguments are required: --$key, $help" . PHP_EOL; exit(1); // If a required argument is missing, exit the program. } } // Extract values from the parsed arguments. $region = $options["region"]; // The region where the bucket is located. $bucket = $options["bucket"]; // The bucket name. $key = $options["key"]; // The object name. $expire = isset($options["expire"]) ? (int)$options["expire"] : 900; // The expiration time. Default: 900 seconds. // Load the credentials from environment variables. // Use EnvironmentVariableCredentialsProvider to read the Access Key ID and Access Key Secret from environment variables. $credentialsProvider = new Oss\Credentials\EnvironmentVariableCredentialsProvider(); // Use the default configurations of the SDK. $cfg = Oss\Config::loadDefault(); $cfg->setCredentialsProvider($credentialsProvider); // Set the credential provider. $cfg->setRegion($region); // Set the region where the bucket is located. if (isset($options["endpoint"])) { $cfg->setEndpoint($options["endpoint"]); // If an endpoint is provided, set it. } try { // Create an OSS client instance. $client = new Oss\Client($cfg); // Create a GetObjectRequest object to download the object. $request = new Oss\Models\GetObjectRequest(bucket:$bucket, key:$key); // Call the presign method to generate a signed URL and set the expiration time. $result = $client->presign($request, [ 'expires' => new \DateInterval("PT{$expire}S") // PT stands for Period Time, and S stands for seconds. ]); // Output the signed URL. echo "Signed URL: " . $result->url . PHP_EOL; } catch (Exception $e) { echo "Error: " . $e->getMessage() . PHP_EOL; exit(1); } -
Les autres utilisateurs téléchargent l'objet en utilisant l'URL signée pour la requête 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 signée pour une requête GET afin de télécharger une version spécifique d'un objet
Télécharger un objet avec un en-tête de requête spécifique à l'aide d'une URL signée
Générer une URL signée pour le téléchargement à l'aide d'un nom de domaine personnalisé
Références
Pour consulter l'exemple de code complet relatif à la génération d'URL signées, rendez-vous sur la page GitHub example.
Pour en savoir plus sur l'opération API Presign, consultez la documentation Presign.