De forma predeterminada, los objetos en un bucket de Object Storage Service (OSS) son privados y solo el propietario del objeto puede acceder a ellos. Este tema describe cómo usar el SDK de PHP de OSS para generar una URL firmada para una solicitud GET. La URL firmada es válida durante un periodo especificado y permite que otros usuarios descarguen temporalmente el objeto. Se puede acceder a la URL varias veces antes de que caduque. Una vez que la URL caduca, debe generar una nueva.
Notas
El código de ejemplo en este tema utiliza el ID de región China (Hangzhou),
cn-hangzhou, como ejemplo. De forma predeterminada, usa un endpoint público. Si desea acceder a OSS desde otros servicios de Alibaba Cloud en la misma región, utilice un endpoint interno. Para obtener más información sobre las regiones y endpoints compatibles con OSS, consulte Regions and endpoints.Este tema utiliza variables de entorno para obtener las credenciales de acceso como ejemplo. Para ver más ejemplos sobre cómo configurar las credenciales de acceso, consulte Configure access credentials for PHP.
No necesita permisos especiales para generar una URL firmada. Sin embargo, un tercero solo podrá descargar correctamente el objeto mediante la URL firmada si usted cuenta con el permiso
oss:GetObject. Para obtener más información sobre cómo otorgar permisos, consulte Grant custom access policies to a RAM user.El código de ejemplo en este tema utiliza una URL firmada V4, cuya validez máxima es de 7 días. Para obtener más información, consulte Signature V4 (recommended).
Procedimiento
A continuación se describe el procedimiento para descargar un objeto mediante una URL prefirmada:
Parámetros
|
Parámetro |
Obligatorio |
Descripción |
Ejemplo |
|
|
Sí |
La región donde se encuentra el bucket. |
|
|
|
Sí |
El nombre del bucket. |
|
|
|
Sí |
El nombre del objeto, incluida la ruta. |
|
|
|
No |
El tiempo de caducidad en segundos. Valor predeterminado: 900. |
|
|
|
No |
El endpoint. Si no se especifica, el sistema utiliza automáticamente el endpoint público correspondiente según la región. |
|
Código de ejemplo
-
El propietario del objeto genera una URL firmada para una solicitud 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); } -
Otros usuarios descargan el objeto mediante la URL firmada para la solicitud 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; }
Escenarios comunes
Generación de una URL firmada para una solicitud GET con el fin de descargar una versión específica de un objeto
Descarga de un objeto con un encabezado de solicitud específico mediante una URL firmada
Generación de una URL firmada para descarga mediante un nombre de dominio personalizado
Referencias
Para consultar el código de ejemplo completo sobre la generación de URLs firmadas, véase el ejemplo en GitHub.
Para obtener más información sobre la operación de API Presign, consulte Presign.