Por padrão, a lista de controle de acesso (ACL) de um objeto em um bucket do Object Storage Service (OSS) é privada. Somente o proprietário do objeto tem permissão para acessá-lo. Este tópico descreve como usar o OSS SDK for Python para gerar uma URL pré-assinada que permite a um usuário baixar um objeto específico dentro de um período determinado pelo método HTTP GET. Durante o período de validade, o usuário pode acessar o objeto repetidamente por meio da URL pré-assinada. Se a URL expirar, gere uma nova para estender o acesso do usuário.
Notas de uso
O código de exemplo neste tópico usa o ID da região
cn-hangzhou, correspondente à região China (Hangzhou). O endpoint público é usado por padrão para acessar recursos em um bucket. Para acessar os recursos do bucket a partir de outros serviços da Alibaba Cloud na mesma região onde o bucket está localizado, use o endpoint interno. Para mais informações sobre regiões e endpoints do OSS, consulte Regiões e endpoints.Não são necessárias permissões especiais para gerar uma URL pré-assinada. No entanto, para que terceiros baixem o objeto usando essa URL, o usuário que a gera deve possuir a permissão
oss:GetObject. Para saber mais sobre como conceder permissões, consulte Conceder permissões personalizadas a um usuário RAM.Este tópico usa o algoritmo de assinatura V4 para gerar URLs pré-assinadas com validade de até 7 dias. Para mais detalhes, consulte (Recomendado) Assinaturas V4 em URLs pré-assinadas.
Procedimento
O procedimento a seguir descreve como baixar um objeto usando uma URL pré-assinada:
Definição do método
Chame o método presign para gerar uma URL pré-assinada que concede acesso temporário a um objeto do OSS. Essa URL pode ser usada várias vezes antes de expirar.
A linha abaixo mostra a sintaxe do método presign:
presign(request: GetObjectRequest, **kwargs) → PresignResult
Parâmetros da solicitação
|
Parâmetro |
Tipo |
Descrição |
|
request |
GetObjectRequest |
A operação de API que a URL pré-assinada deve suportar. Para mais informações, consulte Client.presign. |
|
expires |
datetime.timedelta |
Período de validade da URL pré-assinada a partir do momento atual. Este parâmetro é opcional. Por exemplo, para definir uma validade de 30 minutos, configure expires como 30 * time.Minute. Se não for especificado, a URL terá uma validade padrão de 15 minutos. |
|
expiration |
datetime.datetime |
Data e hora absolutas de expiração da URL pré-assinada. Parâmetro opcional. |
Ao usar o algoritmo de assinatura V4, a validade máxima é de sete dias. Se ambos os parâmetros expiration e expires forem especificados, expiration terá precedência.
Parâmetros de resposta
|
Tipo |
Descrição |
|
PresignResult |
Resultados retornados, incluindo a URL pré-assinada, o método HTTP, o tempo de expiração e os cabeçalhos de solicitação definidos na requisição. Para mais detalhes, consulte PresignResult. |
Conteúdo de PresignResult
|
Parâmetro |
Tipo |
Descrição |
|
method |
str |
Método HTTP correspondente à operação de API especificada na solicitação presign. Por exemplo, o método HTTP da operação GetObject é GET. |
|
url |
str |
A URL pré-assinada gerada. |
|
expiration |
datetime |
Momento de expiração da URL pré-assinada. |
|
signed_headers |
MutableMapping |
Cabeçalhos assinados especificados na solicitação. Se content_type for definido, por exemplo, esse valor será retornado. |
Para obter mais informações sobre o método presign, consulte presign.
Código de exemplo
-
Gere uma URL pré-assinada que permita solicitações HTTP GET:
import argparse import alibabacloud_oss_v2 as oss # Create a command-line parameter parser and describe the purpose of the script. parser = argparse.ArgumentParser(description="presign get object sample") # Specify the --region parameter to indicate the region in which the bucket is located. This parameter is required. parser.add_argument('--region', help='The region in which the bucket is located.', required=True) # Specify the --bucket parameter to indicate the name of the bucket in which the object is stored. This parameter is required. parser.add_argument('--bucket', help='The name of the bucket.', required=True) # Specify the --endpoint parameter to indicate the endpoint of the region in which the bucket is located. This parameter is optional. parser.add_argument('--endpoint', help='The domain names that other services can use to access OSS') # Specify the --key parameter to indicate the name of the object. This parameter is required. parser.add_argument('--key', help='The name of the object.', required=True) def main(): # Parse the command-line parameters to obtain the specified values. args = parser.parse_args() # From the environment variables, load the authentication information required to access OSS. credentials_provider = oss.credentials.EnvironmentVariableCredentialsProvider() # Use the default configuration to create a cfg object and specify the credential provider. cfg = oss.config.load_default() cfg.credentials_provider = credentials_provider # Set the region attribute of the cfg object to the region provided in the command line. cfg.region = args.region # If a custom endpoint is provided, update the endpoint attribute of the cfg object with the provided endpoint. if args.endpoint is not None: cfg.endpoint = args.endpoint # Use the preceding settings to initialize the OSSClient instance. client = oss.Client(cfg) # Initiate a request to generate a presigned URL. pre_result = client.presign( oss.GetObjectRequest( bucket=args.bucket, # Specify the bucket name. key=args.key, # Specify the object key. ) ) # Display the HTTP method, expiration time, and presigned URL. print(f'method: {pre_result.method},' f' expiration: {pre_result.expiration.strftime("%Y-%m-%dT%H:%M:%S.000Z")},' f' url: {pre_result.url}' ) # Display the signed headers. for key, value in pre_result.signed_headers.items(): print(f'signed headers key: {key}, signed headers value: {value}') # Call the main function to start the processing logic when the script is directly run. if __name__ == "__main__": main() # Specify the entry point of the script. The control flow starts here. -
Use a URL pré-assinada para baixar o objeto.
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; }
Cenários comuns
Gerar uma URL pré-assinada que permita solicitações HTTP GET para uma versão específica de um objeto
Baixar um objeto usando uma URL pré-assinada que contenha cabeçalhos de solicitação específicos
Forçar o download de um objeto usando uma URL pré-assinada
Gerar uma URL pré-assinada que permita downloads de objetos usando um endpoint personalizado
Referências
Para obter o código de exemplo completo sobre como baixar um objeto usando uma URL pré-assinada, consulte presigner_get_object.py.