Le propriétaire du fichier génère une URL pré-signée pour la méthode PUT, incluant des en-têtes de requête spécifiques et des métadonnées personnalisées.
import argparse
import requests
import alibabacloud_oss_v2 as oss
from datetime import datetime, timedelta
# Create a command-line argument parser and describe the script's purpose: to generate a presigned PUT request URL for an object (Presign Put Object).
parser = argparse.ArgumentParser(description="presign put object sample")
# Define command-line arguments, including the required region, bucket name, endpoint, and object key.
parser.add_argument('--region', help='The region in which the bucket is located.', required=True)
parser.add_argument('--bucket', help='The name of the bucket.', required=True)
parser.add_argument('--endpoint', help='The domain names that other services can use to access OSS')
parser.add_argument('--key', help='The name of the object.', required=True)
def main():
# Parse command-line arguments to get user-provided values.
args = parser.parse_args()
# Load access credential information from environment variables for identity verification.
credentials_provider = oss.credentials.EnvironmentVariableCredentialsProvider()
# Create a configuration object using the SDK's default settings and set the authentication provider.
cfg = oss.config.load_default()
cfg.credentials_provider = credentials_provider
# Set the region property of the configuration object based on the command-line arguments.
cfg.region = args.region
# If a custom endpoint is provided, update the endpoint property in the configuration object.
if args.endpoint is not None:
cfg.endpoint = args.endpoint
# Initialize the OSS client with the above configuration to interact with OSS.
client = oss.Client(cfg)
# Send a request to generate a presigned PUT request for the specified object.
pre_result = client.presign(oss.PutObjectRequest(
bucket=args.bucket, # Bucket name
key=args.key, # Object key
content_type='text/plain;charset=utf8', # Specify the content type.
storage_class='Standard', # Specify the storage class.
metadata={
'key1': 'value1', # Specify the metadata.
'key2': 'value2' # Specify the metadata.
}
),expires=timedelta(seconds=3600)) # Set the expiration time in seconds. Here, it is set to 3600 seconds.
# Print the method, expiration time, and URL of the presigned request to confirm the validity of the link.
print(f'method: {pre_result.method},'
f' expiration: {pre_result.expiration.strftime("%Y-%m-%dT%H:%M:%S.000Z")},'
f' url: {pre_result.url}'
)
# Print the signed header information of the presigned request. This information will be included in the HTTP headers when the actual request is sent.
for key, value in pre_result.signed_headers.items():
print(f'signed headers key: {key}, signed headers value: {value}')
# When this script is executed directly, call the main function to start the processing logic.
if __name__ == "__main__":
main() # Script entry point. The program flow starts here.
Un autre utilisateur télécharge le fichier en utilisant l’URL pré-signée pour la méthode PUT.
curl
curl -X PUT \
-H "Content-Type: text/plain;charset=utf8" \
-H "x-oss-storage-class: Standard" \
-H "x-oss-meta-key1: value1" \
-H "x-oss-meta-key2: value2" \
-T "C:\\Users\\demo.txt" \
"https://exampleobject.oss-cn-hangzhou.aliyuncs.com/exampleobject.txt?x-oss-date=20241112T083238Z&x-oss-expires=3599&x-oss-signature-version=OSS4-HMAC-SHA256&x-oss-credential=LTAI****************%2F20241112%2Fcn-hangzhou%2Foss%2Faliyun_v4_request&x-oss-signature=ed5a******************************************************"
Java
package com.aliyun.sample;
import com.aliyun.oss.internal.OSSHeaders;
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.*;
public class SignUrlUpload {
public static void main(String[] args) throws Throwable {
CloseableHttpClient httpClient = null;
CloseableHttpResponse response = null;
// Replace <signedUrl> with the authorized URL.
URL signedUrl = new URL("<signedUrl>");
// Specify the full path of the local file. If you do not specify a local path, the file is uploaded from the project path of the sample program by default.
String pathName = "C:\\Users\\demo.txt";
// Set the request headers. The request header information must be the same as the information used when the URL was generated.
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 ContentType.
headers.put(OSSHeaders.CONTENT_TYPE, "text/plain;charset=utf8");
// Set the custom user metadata. The custom user metadata must be the same as the information used when the URL was generated.
Map<String, String> userMetadata = new HashMap<String, String>();
userMetadata.put("key1","value1");
userMetadata.put("key2","value2");
try {
HttpPut put = new HttpPut(signedUrl.toString());
System.out.println(put);
HttpEntity entity = new FileEntity(new File(pathName));
put.setEntity(entity);
// If you set header parameters, such as user metadata and storage class, when you generate the presigned URL, you must also send these parameters to the server when you use the presigned URL to upload the file. A signature error is reported if the parameters sent to the server are inconsistent with the signed parameters.
for(Map.Entry<String, String> header: headers.entrySet()){
put.addHeader(header.getKey(), header.getValue());
}
for(Map.Entry<String, String> meta: userMetadata.entrySet()){
// If you use userMeta, the SDK internally adds the 'x-oss-meta-' prefix. When you use other methods to generate a presigned URL for an upload, you must also add the 'x-oss-meta-' prefix to the userMeta.
put.addHeader("x-oss-meta-"+meta.getKey(), meta.getValue());
}
httpClient = HttpClients.createDefault();
response = httpClient.execute(put);
System.out.println("Status code returned for the upload:"+response.getStatusLine().getStatusCode());
if(response.getStatusLine().getStatusCode() == 200){
System.out.println("Upload successful using network library.");
}
System.out.println(response.toString());
} catch (Exception e){
e.printStackTrace();
} finally {
if (response != null) {
response.close();
}
if (httpClient != null) {
httpClient.close();
}
}
}
}
Go
package main
import (
"bytes"
"fmt"
"io/ioutil"
"net/http"
"os"
)
func uploadFile(signedUrl string, filePath string, headers map[string]string, metadata map[string]string) error {
// Open the file.
file, err := os.Open(filePath)
if err != nil {
return err
}
defer file.Close()
// Read the file content.
fileBytes, err := ioutil.ReadAll(file)
if err != nil {
return err
}
// Create a request.
req, err := http.NewRequest("PUT", signedUrl, bytes.NewBuffer(fileBytes))
if err != nil {
return err
}
// Set the request headers.
for key, value := range headers {
req.Header.Set(key, value)
}
// Set the custom user metadata.
for key, value := range metadata {
req.Header.Set(fmt.Sprintf("x-oss-meta-%s", key), value)
}
// Send the request.
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
return err
}
defer resp.Body.Close()
// Process the response.
fmt.Printf("Status code returned for the upload: %d\n", resp.StatusCode)
if resp.StatusCode == 200 {
fmt.Println("Upload successful using network library.")
} else {
fmt.Println("Upload failed.")
}
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
return nil
}
func main() {
// Replace <signedUrl> with the authorized URL.
signedUrl := "<signedUrl>"
// Specify the full path of the local file. If you do not specify a local path, the file is uploaded from the project path of the sample program by default.
filePath := "C:\\Users\\demo.txt"
// Set the request headers. The request header information must be the same as the information used when the URL was generated.
headers := map[string]string{
"Content-Type": "text/plain;charset=utf8",
"x-oss-storage-class": "Standard",
}
// Set the custom user metadata. The custom user metadata must be the same as the information used when the URL was generated.
metadata := map[string]string{
"key1": "value1",
"key2": "value2",
}
err := uploadFile(signedUrl, filePath, headers, metadata)
if err != nil {
fmt.Printf("An error occurred: %v\n", err)
}
}
Python
import requests
from requests.auth import HTTPBasicAuth
import os
def upload_file(signed_url, file_path, headers=None, metadata=None):
"""
Use a presigned URL to upload a file to OSS.
:param signed_url: The presigned URL.
:param file_path: The full path of the file to upload.
:param headers: Optional. Custom HTTP headers.
:param metadata: Optional. Custom metadata.
:return: None
"""
if not headers:
headers = {}
if not metadata:
metadata = {}
# Update headers and add the metadata prefix.
for key, value in metadata.items():
headers[f'x-oss-meta-{key}'] = value
try:
with open(file_path, 'rb') as file:
response = requests.put(signed_url, data=file, headers=headers)
print(f"Status code returned for the upload: {response.status_code}")
if response.status_code == 200:
print("Upload successful using network library.")
else:
print("Upload failed.")
print(response.text)
except Exception as e:
print(f"An error occurred: {e}")
if __name__ == "__main__":
# Replace <signedUrl> with the authorized URL.
signed_url = "<signedUrl>"
# Specify the full path of the local file. If you do not specify a local path, the file is uploaded from the directory where the script is located by default.
file_path = "C:\\Users\\demo.txt"
# Set the request headers. The request header information must be the same as the information used when the URL was generated.
headers = {
"Content-Type": "text/plain;charset=utf8",
"x-oss-storage-class": "Standard"
}
# Set the custom user metadata. The custom user metadata must be the same as the information used when the URL was generated.
metadata = {
"key1": "value1",
"key2": "value2"
}
upload_file(signed_url, file_path, headers, metadata)
Node.js
const fs = require('fs');
const axios = require('axios');
async function uploadFile(signedUrl, filePath, headers = {}, metadata = {}) {
try {
// Update headers and add the metadata prefix.
for (const [key, value] of Object.entries(metadata)) {
headers[`x-oss-meta-${key}`] = value;
}
// Read the file stream.
const fileStream = fs.createReadStream(filePath);
// Send a PUT request.
const response = await axios.put(signedUrl, fileStream, {
headers: headers
});
console.log(`Status code returned for the upload: ${response.status}`);
if (response.status === 200) {
console.log("Upload successful using network library.");
} else {
console.log("Upload failed.");
}
console.log(response.data);
} catch (error) {
console.error(`An error occurred: ${error.message}`);
}
}
// Main function.
(async () => {
// Replace <signedUrl> with the authorized URL.
const signedUrl = "<signedUrl>";
// Specify the full path of the local file. If you do not specify a local path, the file is uploaded from the directory where the script is located by default.
const filePath = "C:\\Users\\demo.txt";
// Set the request headers. The request header information must be the same as the information used when the URL was generated.
const headers = {
"Content-Type": "text/plain;charset=utf8",
"x-oss-storage-class": "Standard"
};
// Set the custom user metadata. The custom user metadata must be the same as the information used when the URL was generated.
const metadata = {
"key1": "value1",
"key2": "value2"
};
await uploadFile(signedUrl, filePath, headers, metadata);
})();
Browser.js
Si vous rencontrez une erreur de discordance de signature 403 lors du téléchargement d’un fichier avec Browser.js, cela est généralement dû au fait que le navigateur ajoute automatiquement l’en-tête de requête Content-Type, qui n’a pas été inclus lors de la génération de l’URL pré-signée. Cette incompatibilité entraîne un échec de la vérification de la signature. Pour résoudre ce problème, vous devez spécifier l’en-tête de requête Content-Type lors de la génération de l’URL pré-signée.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>File Upload Example</title>
</head>
<body>
<h1>File Upload Example (Java SDK)</h1>
<input type="file" id="fileInput" />
<button id="uploadButton">Upload File</button>
<script>
// Replace this with the actual presigned URL.
const signedUrl = "<signedUrl>";
document.getElementById('uploadButton').addEventListener('click', async () => {
const fileInput = document.getElementById('fileInput');
const file = fileInput.files[0];
if (file) {
try {
await upload(file, signedUrl);
} catch (error) {
console.error('Error during upload:', error);
alert('Upload failed: ' + error.message);
}
} else {
alert('Please select a file to upload.');
}
});
const upload = async (file, presignedUrl) => {
const headers = {
"Content-Type": "text/plain;charset=utf8",
'x-oss-storage-class': 'Standard',
'x-oss-meta-key1': 'value1',
'x-oss-meta-key2': 'value2'
};
const response = await fetch(presignedUrl, {
method: 'PUT',
headers: headers,
body: file
});
if (!response.ok) {
throw new Error(`Upload failed, status: ${response.status}`);
}
alert('File uploaded successfully');
console.log('File uploaded successfully');
};
</script>
</body>
</html>
C#
using System.Net.Http.Headers;
// Specify the full path of the local file. If you do not specify a local path, the file is uploaded from the project path of the sample program by default.
var filePath = "C:\\Users\\demo.txt";
// Replace <signedUrl> with the authorized URL.
var presignedUrl = "<signedUrl>";
// Create an HTTP client and open the local file stream.
using var httpClient = new HttpClient();
using var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read);
using var content = new StreamContent(fileStream);
// Create a PUT request.
var request = new HttpRequestMessage(HttpMethod.Put, presignedUrl);
request.Content = content;
// If you set header parameters, such as user metadata and storage class, when you generate the presigned URL, you must also send these parameters to the server when you use the presigned URL to upload the file. A signature error is reported if the parameters sent to the server are inconsistent with the signed parameters.
// Set the request headers. The request header information must be the same as the information used when the URL was generated.
request.Content.Headers.ContentType = new MediaTypeHeaderValue("text/plain") { CharSet = "utf8" }; // Specify the ContentType.
// Set the custom user metadata. The custom user metadata must be the same as the information used when the URL was generated.
request.Content.Headers.Add("x-oss-meta-key1", "value1");
request.Content.Headers.Add("x-oss-meta-key2", "value2");
// Specify the storage class of the object.
request.Content.Headers.Add("x-oss-storage-class", "Standard");
// Print the request headers.
Console.WriteLine("Request headers:");
foreach (var header in request.Content.Headers)
{
Console.WriteLine($"{header.Key}: {string.Join(", ", header.Value)}");
}
// Send the request.
var response = await httpClient.SendAsync(request);
// Process the response.
if (response.IsSuccessStatusCode)
{
Console.WriteLine($"Upload successful! Status code: {response.StatusCode}");
Console.WriteLine("Response headers:");
foreach (var header in response.Headers)
{
Console.WriteLine($"{header.Key}: {string.Join(", ", header.Value)}");
}
}
else
{
string responseContent = await response.Content.ReadAsStringAsync();
Console.WriteLine($"Upload failed! Status code: {response.StatusCode}");
Console.WriteLine("Response content: " + responseContent);
}
C++
#include <iostream>
#include <fstream>
#include <curl/curl.h>
#include <map>
#include <string>
// Callback function to handle the HTTP response.
size_t WriteCallback(void* contents, size_t size, size_t nmemb, std::string* output) {
size_t totalSize = size * nmemb;
output->append((char*)contents, totalSize);
return totalSize;
}
void uploadFile(const std::string& signedUrl, const std::string& filePath, const std::map<std::string, std::string>& headers, const std::map<std::string, std::string>& metadata) {
CURL* curl;
CURLcode res;
std::string readBuffer;
curl_global_init(CURL_GLOBAL_DEFAULT);
curl = curl_easy_init();
if (curl) {
// Set the URL.
curl_easy_setopt(curl, CURLOPT_URL, signedUrl.c_str());
// Set the request method to PUT.
curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L);
// Open the file.
FILE* file = fopen(filePath.c_str(), "rb");
if (!file) {
std::cerr << "Unable to open file: " << filePath << std::endl;
return;
}
// Set the file size.
fseek(file, 0, SEEK_END);
long fileSize = ftell(file);
rewind(file);
// Set the file read callback.
curl_easy_setopt(curl, CURLOPT_READDATA, file);
curl_easy_setopt(curl, CURLOPT_INFILESIZE_LARGE, (curl_off_t)fileSize);
// Set the request headers.
struct curl_slist* chunk = nullptr;
for (const auto& header : headers) {
std::string headerStr = header.first + ": " + header.second;
chunk = curl_slist_append(chunk, headerStr.c_str());
}
for (const auto& meta : metadata) {
std::string metaStr = "x-oss-meta-" + meta.first + ": " + meta.second;
chunk = curl_slist_append(chunk, metaStr.c_str());
}
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, chunk);
// Set the response handling callback.
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer);
// Execute the request.
res = curl_easy_perform(curl);
// Check the response.
if (res != CURLE_OK) {
std::cerr << "curl_easy_perform() failed: " << curl_easy_strerror(res) << std::endl;
} else {
long responseCode;
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &responseCode);
std::cout << "Status code returned for the upload: " << responseCode << std::endl;
if (responseCode == 200) {
std::cout << "Upload successful using network library." << std::endl;
} else {
std::cout << "Upload failed." << std::endl;
}
std::cout << readBuffer << std::endl;
}
// Clean up.
fclose(file);
curl_slist_free_all(chunk);
curl_easy_cleanup(curl);
}
curl_global_cleanup();
}
int main() {
// Replace <signedUrl> with the authorized URL.
std::string signedUrl = "<signedUrl>";
// Specify the full path of the local file. If you do not specify a local path, the file is uploaded from the project path of the sample program by default.
std::string filePath = "C:\\Users\\demo.txt";
// Set the request headers. The request header information must be the same as the information used when the URL was generated.
std::map<std::string, std::string> headers = {
{"Content-Type", "text/plain;charset=utf8"},
{"x-oss-storage-class", "Standard"}
};
// Set the custom user metadata. The custom user metadata must be the same as the information used when the URL was generated.
std::map<std::string, std::string> metadata = {
{"key1", "value1"},
{"key2", "value2"}
};
uploadFile(signedUrl, filePath, headers, metadata);
return 0;
}
Android
import android.os.AsyncTask;
import android.util.Log;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
public class SignUrlUploadActivity extends AppCompatActivity {
private static final String TAG = "SignUrlUploadActivity";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Replace <signedUrl> with the authorized URL.
String signedUrl = "<signedUrl>";
// Specify the full path of the local file. If you do not specify a local path, the file is uploaded from the project path of the sample program by default.
String pathName = "/storage/emulated/0/demo.txt";
// Set the request headers. The request header information must be the same as the information used when the URL was generated.
Map<String, String> headers = new HashMap<>();
headers.put("Content-Type", "text/plain;charset=utf8");
headers.put("x-oss-storage-class", "Standard");
// Set the custom user metadata. The custom user metadata must be the same as the information used when the URL was generated.
Map<String, String> userMetadata = new HashMap<>();
userMetadata.put("key1", "value1");
userMetadata.put("key2", "value2");
new UploadTask().execute(signedUrl, pathName, headers, userMetadata);
}
private class UploadTask extends AsyncTask<Object, Void, Integer> {
@Override
protected Integer doInBackground(Object... params) {
String signedUrl = (String) params[0];
String pathName = (String) params[1];
Map<String, String> headers = (Map<String, String>) params[2];
Map<String, String> userMetadata = (Map<String, String>) params[3];
try {
URL url = new URL(signedUrl);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("PUT");
connection.setDoOutput(true);
connection.setUseCaches(false);
// Set the request headers.
for (Entry<String, String> header : headers.entrySet()) {
connection.setRequestProperty(header.getKey(), header.getValue());
}
// Set the custom user metadata.
for (Entry<String, String> meta : userMetadata.entrySet()) {
connection.setRequestProperty("x-oss-meta-" + meta.getKey(), meta.getValue());
}
// Read the file.
File file = new File(pathName);
FileInputStream fileInputStream = new FileInputStream(file);
DataOutputStream dos = new DataOutputStream(connection.getOutputStream());
byte[] buffer = new byte[1024];
int count;
while ((count = fileInputStream.read(buffer)) != -1) {
dos.write(buffer, 0, count);
}
fileInputStream.close();
dos.flush();
dos.close();
// Get the response.
int responseCode = connection.getResponseCode();
Log.d(TAG, "Status code returned for the upload: " + responseCode);
if (responseCode == 200) {
Log.d(TAG, "Upload successful using network library.");
} else {
Log.d(TAG, "Upload failed.");
}
InputStream is = connection.getInputStream();
byte[] responseBuffer = new byte[1024];
StringBuilder responseStringBuilder = new StringBuilder();
while ((count = is.read(responseBuffer)) != -1) {
responseStringBuilder.append(new String(responseBuffer, 0, count));
}
Log.d(TAG, responseStringBuilder.toString());
return responseCode;
} catch (IOException e) {
e.printStackTrace();
return -1;
}
}
@Override
protected void onPostExecute(Integer result) {
super.onPostExecute(result);
if (result == 200) {
Toast.makeText(SignUrlUploadActivity.this, "Upload successful.", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(SignUrlUploadActivity.this, "Upload failed.", Toast.LENGTH_SHORT).show();
}
}
}
}
Utiliser une URL pré-signée pour effectuer un chargement en plusieurs parties
Utiliser une URL pré-signée pour charger un fichier et configurer les paramètres de rappel de chargement
Par défaut, les objects stockés dans un compartiment Object Storage Service (OSS) sont privés. Seul le propriétaire de l'object dispose des autorisations nécessaires pour effectuer des chargements. Vous pouvez utiliser le SDK OSS pour Python afin de générer une URL pré-signée permettant à d'autres utilisateurs de charger un object. Lors de la génération de cette URL, vous avez la possibilité de définir une durée d'expiration. Tant qu'elle n'a pas expiré, l'URL peut être utilisée plusieurs fois. Attention toutefois : si plusieurs opérations de chargement sont effectuées, l'object risque d'être écrasé. Une fois l'URL arrivée à expiration, elle ne peut plus servir aux chargements. Il vous faudra alors générer une nouvelle URL pré-signée.
Instructions
Remarques d'utilisation
Le code exemple de cette rubrique utilise la région Chine (Hangzhou) (
cn-hangzhou) à titre d'exemple. Un endpoint public est utilisé par défaut. Si vous accédez à OSS depuis un autre service Alibaba Cloud dans la même région, vous devez utiliser un endpoint interne. Pour plus d'informations sur les régions et les endpoints OSS, consultez Régions et endpoints.Aucune autorisation n'est requise pour générer une URL présignée. Toutefois, un tiers ne peut télécharger un fichier avec succès via l'URL présignée que si vous disposez de l'autorisation
oss:PutObject. Pour plus d'informations, consultez Accorder une politique d'accès personnalisée à un utilisateur RAM.Le code exemple de cette rubrique utilise des URL présignées V4, dont la durée de validité maximale est de 7 jours. Pour plus d'informations, consultez Signature V4 (recommandée).
Processus
Pour télécharger un fichier à l'aide d'une URL signée et de la méthode PUT, suivez la procédure ci-dessous :
Définition de la méthode
Vous pouvez générer une URL présignée qui accorde des autorisations d'accès temporaires aux objects d'un bucket et qui peut être utilisée plusieurs fois avant son expiration.
La méthode presign est définie comme suit :
presign(request: PutObjectRequest, **kwargs) → PresignResult
Paramètres de requête
|
Nom du paramètre |
Type |
Description |
|
request |
PutObjectRequest |
Nom de la méthode pour laquelle générer l'URL présignée. Pour plus d'informations, consultez Client.presign. |
|
expires |
datetime.timedelta |
(Facultatif) Durée de vie (TTL) de l'URL présignée, à compter de l'heure actuelle. Par exemple, pour définir une TTL de 30 minutes, utilisez 30 * time.Minute. Si ce paramètre n'est pas spécifié, la valeur par défaut est de 15 minutes. |
|
expiration |
datetime.datetime |
(Facultatif) Date et heure spécifiques d'expiration de l'URL présignée. |
Pour les signatures V4, la durée de validité maximale est de 7 jours. Si vous définissez à la fois Expiration et Expires, le paramètre Expiration est prioritaire.
Valeurs de retour
|
Type |
Description |
|
PresignResult |
Résultat incluant l'URL présignée, la méthode HTTP, l'heure d'expiration et les en-têtes de requête signés. Pour plus d'informations, consultez PresignResult. |
Les valeurs de retour de PresignResult sont répertoriées ci-dessous :
|
Nom du paramètre |
Type |
Description |
|
method |
str |
Méthode HTTP correspondant à l'interface. Par exemple, pour l'interface PutObject, la valeur PUT est renvoyée. |
|
url |
str |
L'URL présignée. |
|
expiration |
datetime |
L'heure d'expiration de l'URL présignée. |
|
signed_headers |
MutableMapping |
En-têtes de requête signés. Par exemple, si vous définissez content_type, les informations relatives à content_type sont renvoyées. |
Pour la définition complète de la méthode presign, consultez presign.
Exemple de code
-
Le propriétaire du fichier génère une URL présignée pour la méthode PUT.
ImportantLorsque vous générez une URL présignée pour la méthode PUT, si vous spécifiez des en-têtes de requête, vous devez inclure les mêmes en-têtes dans la requête PUT utilisant l'URL présignée. Dans le cas contraire, la vérification de la signature échoue.
import argparse import requests import alibabacloud_oss_v2 as oss from datetime import datetime, timedelta # Create a command-line argument parser and describe the script's purpose: to generate a presigned PUT request URL for an object (Presign Put Object). parser = argparse.ArgumentParser(description="presign put object sample") # Define command-line arguments, including the required region, bucket name, endpoint, and object key. parser.add_argument('--region', help='The region in which the bucket is located.', required=True) parser.add_argument('--bucket', help='The name of the bucket.', required=True) parser.add_argument('--endpoint', help='The domain names that other services can use to access OSS') parser.add_argument('--key', help='The name of the object.', required=True) def main(): # Parse command-line arguments to get user-provided values. args = parser.parse_args() # Load access credential information from environment variables for identity verification. credentials_provider = oss.credentials.EnvironmentVariableCredentialsProvider() # Create a configuration object using the SDK's default settings and set the authentication provider. cfg = oss.config.load_default() cfg.credentials_provider = credentials_provider # Set the region property of the configuration object based on the command-line arguments. cfg.region = args.region # If a custom endpoint is provided, update the endpoint property in the configuration object. if args.endpoint is not None: cfg.endpoint = args.endpoint # Initialize the OSS client with the above configuration to interact with OSS. client = oss.Client(cfg) # Send a request to generate a presigned PUT request for the specified object. pre_result = client.presign(oss.PutObjectRequest( bucket=args.bucket, # Bucket name key=args.key, # Object key ),expires=timedelta(seconds=3600)) # Set the expiration time in seconds. Here, it is set to 3600 seconds. # Print the method, expiration time, and URL of the presigned request to confirm the validity of the link. print(f'method: {pre_result.method},' f' expiration: {pre_result.expiration.strftime("%Y-%m-%dT%H:%M:%S.000Z")},' f' url: {pre_result.url}' ) # Print the signed header information of the presigned request. This information will be included in the HTTP headers when the actual request is sent. for key, value in pre_result.signed_headers.items(): print(f'signed headers key: {key}, signed headers value: {value}') # When this script is executed directly, call the main function to start the processing logic. if __name__ == "__main__": main() # Script entry point. The program flow starts here. -
Un autre utilisateur télécharge un fichier à l'aide de l'URL présignée pour la méthode PUT.
curl
curl -X PUT -T /path/to/local/file "https://exampleobject.oss-cn-hangzhou.aliyuncs.com/exampleobject.txt?x-oss-date=20241112T083238Z&x-oss-expires=3599&x-oss-signature-version=OSS4-HMAC-SHA256&x-oss-credential=LTAI****************%2F20241112%2Fcn-hangzhou%2Foss%2Faliyun_v4_request&x-oss-signature=ed5a******************************************************"Java
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.*; public class SignUrlUpload { public static void main(String[] args) throws Throwable { CloseableHttpClient httpClient = null; CloseableHttpResponse response = null; // Replace <signedUrl> with the authorized URL. URL signedUrl = new URL("<signedUrl>"); // Specify the full path of the local file. If you do not specify a local path, the file is uploaded from the project path of the sample program by default. String pathName = "C:\\Users\\demo.txt"; try { HttpPut put = new HttpPut(signedUrl.toString()); System.out.println(put); HttpEntity entity = new FileEntity(new File(pathName)); put.setEntity(entity); httpClient = HttpClients.createDefault(); response = httpClient.execute(put); System.out.println("Status code returned for the upload:"+response.getStatusLine().getStatusCode()); if(response.getStatusLine().getStatusCode() == 200){ System.out.println("Upload successful using network library."); } System.out.println(response.toString()); } catch (Exception e){ e.printStackTrace(); } finally { if (response != null) { response.close(); } if (httpClient != null) { httpClient.close(); } } } }Go
package main import ( "fmt" "io" "net/http" "os" ) func uploadFile(signedUrl, filePath string) error { // Open the file. file, err := os.Open(filePath) if err != nil { return fmt.Errorf("Unable to open file: %w", err) } defer file.Close() // Create a new HTTP client. client := &http.Client{} // Create a PUT request. req, err := http.NewRequest("PUT", signedUrl, file) if err != nil { return fmt.Errorf("Failed to create request: %w", err) } // Send the request. resp, err := client.Do(req) if err != nil { return fmt.Errorf("Failed to send request: %w", err) } defer resp.Body.Close() // Read the response. body, err := io.ReadAll(resp.Body) if err != nil { return fmt.Errorf("Failed to read response: %w", err) } fmt.Printf("Status code returned for the upload: %d\n", resp.StatusCode) if resp.StatusCode == 200 { fmt.Println("Upload successful using network library.") } fmt.Println(string(body)) return nil } func main() { // Replace <signedUrl> with the authorized URL. signedUrl := "<signedUrl>" // Specify the full path of the local file. If you do not specify a local path, the file is uploaded from the project path of the sample program by default. filePath := "C:\\Users\\demo.txt" err := uploadFile(signedUrl, filePath) if err != nil { fmt.Println("An error occurred:", err) } }python
import requests def upload_file(signed_url, file_path): try: # Open the file. with open(file_path, 'rb') as file: # Send a PUT request to upload the file. response = requests.put(signed_url, data=file) print(f"Status code returned for the upload: {response.status_code}") if response.status_code == 200: print("Upload successful using network library.") print(response.text) except Exception as e: print(f"An error occurred: {e}") if __name__ == "__main__": # Replace <signedUrl> with the authorized URL. signed_url = "<signedUrl>" # Specify the full path of the local file. If you do not specify a local path, the file is uploaded from the project path of the sample program by default. file_path = "C:\\Users\\demo.txt" upload_file(signed_url, file_path)Node.js
ImportantSi vous rencontrez une erreur de non-correspondance de signature 403 lors du téléchargement d'un fichier avec Node.js, cela est généralement dû au fait que l'en-tête de requête Content-Type est explicitement défini dans la requête de téléchargement, mais qu'il n'a pas été inclus lors de la génération de l'URL présignée. Cette incompatibilité entraîne un échec de la vérification de la signature. Pour résoudre ce problème, ne définissez pas l'en-tête de requête Content-Type dans la requête de téléchargement ou spécifiez l'en-tête de requête Content-Type lors de la génération de l'URL présignée.
const fs = require('fs'); const axios = require('axios'); async function uploadFile(signedUrl, filePath) { try { // Create a read stream. const fileStream = fs.createReadStream(filePath); // Send a PUT request to upload the file. const response = await axios.put(signedUrl, fileStream); console.log(`Status code returned for the upload: ${response.status}`); if (response.status === 200) { console.log('Upload successful using network library.'); } console.log(response.data); } catch (error) { console.error(`An error occurred: ${error.message}`); } } // Main function. (async () => { // Replace <signedUrl> with the authorized URL. const signedUrl = '<signedUrl>'; // Specify the full path of the local file. If you do not specify a local path, the file is uploaded from the project path of the sample program by default. const filePath = 'C:\\Users\\demo.txt'; await uploadFile(signedUrl, filePath); })();browser.js
ImportantSi vous rencontrez une erreur de non-correspondance de signature 403 lors du téléchargement d'un fichier avec Browser.js, cela est généralement dû au fait que le navigateur ajoute automatiquement l'en-tête de requête Content-Type et que cet en-tête n'a pas été inclus lors de la génération de l'URL présignée. Cette incompatibilité entraîne un échec de la vérification de la signature. Pour résoudre ce problème, vous devez spécifier l'en-tête de requête Content-Type lors de la génération de l'URL présignée.
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>File Upload Example</title> </head> <body> <h1>File Upload Example</h1> <!-- Select a file --> <input type="file" id="fileInput" /> <button id="uploadButton">Upload File</button> <script> // Replace this with the presigned URL generated in Step 1. const signedUrl = "<signedUrl>"; document.getElementById('uploadButton').addEventListener('click', async () => { const fileInput = document.getElementById('fileInput'); const file = fileInput.files[0]; if (!file) { alert('Please select a file to upload.'); return; } try { await upload(file, signedUrl); alert('File uploaded successfully!'); } catch (error) { console.error('Error during upload:', error); alert('Upload failed: ' + error.message); } }); /** * Upload the file to OSS. * @param {File} file - The file to upload. * @param {string} presignedUrl - The presigned URL. */ const upload = async (file, presignedUrl) => { const response = await fetch(presignedUrl, { method: 'PUT', body: file, // Upload the entire file directly. }); if (!response.ok) { throw new Error(`Upload failed, status: ${response.status}`); } console.log('File uploaded successfully'); }; </script> </body> </html>C#
using System.Net.Http.Headers; // Specify the full path of the local file. If you do not specify a local path, the file is uploaded from the project path of the sample program by default. var filePath = "C:\\Users\\demo.txt"; // Replace <signedUrl> with the authorized URL. var presignedUrl = "<signedUrl>"; // Create an HTTP client and open the local file stream. using var httpClient = new HttpClient(); using var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read); using var content = new StreamContent(fileStream); // Create a PUT request. var request = new HttpRequestMessage(HttpMethod.Put, presignedUrl); request.Content = content; // Send the request. var response = await httpClient.SendAsync(request); // Process the response. if (response.IsSuccessStatusCode) { Console.WriteLine($"Upload successful! Status code: {response.StatusCode}"); Console.WriteLine("Response headers:"); foreach (var header in response.Headers) { Console.WriteLine($"{header.Key}: {string.Join(", ", header.Value)}"); } } else { string responseContent = await response.Content.ReadAsStringAsync(); Console.WriteLine($"Upload failed! Status code: {response.StatusCode}"); Console.WriteLine("Response content: " + responseContent); }C++
#include <iostream> #include <fstream> #include <curl/curl.h> void uploadFile(const std::string& signedUrl, const std::string& filePath) { CURL *curl; CURLcode res; curl_global_init(CURL_GLOBAL_DEFAULT); curl = curl_easy_init(); if (curl) { // Set the URL. curl_easy_setopt(curl, CURLOPT_URL, signedUrl.c_str()); // Set the request method to PUT. curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L); // Open the file. FILE *file = fopen(filePath.c_str(), "rb"); if (!file) { std::cerr << "Unable to open file: " << filePath << std::endl; return; } // Get the file size. fseek(file, 0, SEEK_END); long fileSize = ftell(file); fseek(file, 0, SEEK_SET); // Set the file size. curl_easy_setopt(curl, CURLOPT_INFILESIZE_LARGE, (curl_off_t)fileSize); // Set the input file handle. curl_easy_setopt(curl, CURLOPT_READDATA, file); // Execute the request. res = curl_easy_perform(curl); if (res != CURLE_OK) { std::cerr << "curl_easy_perform() failed: " << curl_easy_strerror(res) << std::endl; } else { long httpCode = 0; curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &httpCode); std::cout << "Status code returned for the upload: " << httpCode << std::endl; if (httpCode == 200) { std::cout << "Upload successful using network library." << std::endl; } } // Close the file. fclose(file); // Clean up. curl_easy_cleanup(curl); } curl_global_cleanup(); } int main() { // Replace <signedUrl> with the authorized URL. std::string signedUrl = "<signedUrl>"; // Specify the full path of the local file. If you do not specify a local path, the file is uploaded from the project path of the sample program by default. std::string filePath = "C:\\Users\\demo.txt"; uploadFile(signedUrl, filePath); return 0; }Android
package com.example.signurlupload; import android.os.AsyncTask; import android.util.Log; import java.io.DataOutputStream; import java.io.FileInputStream; import java.io.IOException; import java.net.HttpURLConnection; import java.net.URL; public class SignUrlUploadActivity { private static final String TAG = "SignUrlUploadActivity"; public void uploadFile(String signedUrl, String filePath) { new UploadTask().execute(signedUrl, filePath); } private class UploadTask extends AsyncTask<String, Void, String> { @Override protected String doInBackground(String... params) { String signedUrl = params[0]; String filePath = params[1]; HttpURLConnection connection = null; DataOutputStream dos = null; FileInputStream fis = null; try { URL url = new URL(signedUrl); connection = (HttpURLConnection) url.openConnection(); connection.setRequestMethod("PUT"); connection.setDoOutput(true); connection.setRequestProperty("Content-Type", "application/octet-stream"); fis = new FileInputStream(filePath); dos = new DataOutputStream(connection.getOutputStream()); byte[] buffer = new byte[1024]; int length; while ((length = fis.read(buffer)) != -1) { dos.write(buffer, 0, length); } dos.flush(); dos.close(); fis.close(); int responseCode = connection.getResponseCode(); Log.d(TAG, "Status code returned for the upload: " + responseCode); if (responseCode == 200) { Log.d(TAG, "Upload successful using network library."); } return "Upload complete. Status code: " + responseCode; } catch (IOException e) { e.printStackTrace(); return "Upload failed: " + e.getMessage(); } finally { if (connection != null) { connection.disconnect(); } } } @Override protected void onPostExecute(String result) { Log.d(TAG, result); } } public static void main(String[] args) { SignUrlUploadActivity activity = new SignUrlUploadActivity(); // Replace <signedUrl> with the authorized URL. String signedUrl = "<signedUrl>"; // Specify the full path of the local file. If you do not specify a local path, the file is uploaded from the project path of the sample program by default. String filePath = "C:\\Users\\demo.txt"; activity.uploadFile(signedUrl, filePath); } }
FAQ
Si j'utilise une signature temporaire pour télécharger un fichier et que la signature expire pendant le téléchargement, le téléchargement échouera-t-il ?
Si je ne définis pas d'en-têtes de requête ni de métadonnées personnalisées lors de la génération de l'URL, dois-je les configurer lors de l'utilisation de l'URL pour un téléchargement ?
Références
Pour le code exemple complet relatif au téléchargement d'un fichier à l'aide d'une URL présignée, consultez presigner_put_object.py.
Pour le code exemple complet relatif à l'exécution d'un téléchargement multipartie à l'aide d'une URL présignée, consultez presigner_complete_multipart_upload.py.