Secara default, daftar kontrol akses (ACL) dari sebuah objek Object Storage Service (OSS) di dalam bucket bersifat pribadi. Hanya pemilik objek yang memiliki izin untuk mengunggah objek ke bucket. Anda dapat menggunakan OSS SDK untuk Python untuk menghasilkan URL yang ditandatangani dan membagikan URL tersebut dengan pengguna untuk mengizinkan mereka mengunggah objek. Saat menghasilkan URL yang ditandatangani, Anda dapat menentukan periode validitas untuk membatasi jangka waktu pengguna dapat mengunggah objek. Selama periode validitas, pengguna dapat menggunakan URL tersebut untuk mengunggah objek berkali-kali. Jika objek diunggah berkali-kali, objek sebelumnya mungkin tertimpa. Setelah periode validitas berakhir, pengguna tidak dapat lagi menggunakan URL tersebut untuk mengunggah objek, dan Anda harus menghasilkan URL baru.
Catatan Penggunaan
Kode contoh dalam topik ini menggunakan ID wilayah
cn-hangzhoudari Wilayah Hangzhou, Tiongkok. Secara default, titik akhir publik digunakan untuk mengakses sumber daya di bucket. Jika Anda ingin mengakses sumber daya di bucket menggunakan layanan Alibaba Cloud lainnya di wilayah yang sama dengan bucket tersebut, gunakan titik akhir internal. Untuk informasi lebih lanjut tentang wilayah dan titik akhir OSS, lihat Wilayah dan Titik Akhir.Anda tidak memerlukan izin khusus untuk menghasilkan URL yang ditandatangani. Namun, untuk mengizinkan pihak ketiga menggunakan URL yang ditandatangani untuk mengunggah objek, Anda harus memiliki izin
oss:PutObject. Untuk informasi lebih lanjut, lihat Memberikan Izin kepada Pengguna RAM Menggunakan Kebijakan Kustom.Dalam topik ini, URL yang ditandatangani mencakup tanda tangan V4 dengan periode validitas hingga tujuh hari. Untuk informasi lebih lanjut, lihat (Direkomendasikan) Tanda Tangan V4 dalam URL yang Ditandatangani.
Proses
Gambar berikut menunjukkan cara menggunakan URL yang ditandatangani untuk mengizinkan permintaan HTTP PUT mengunggah objek ke OSS.
Metode
Anda dapat memanggil operasi tertentu untuk menghasilkan URL yang ditandatangani dan menggunakan URL tersebut untuk memberikan izin akses sementara pada objek di bucket. URL yang ditandatangani dapat digunakan beberapa kali sebelum kedaluwarsa.
Sintaks:
presign(request: PutObjectRequest, **kwargs) → PresignResultParameter Permintaan
Parameter | Tipe | Deskripsi |
request | PutObjectRequest | Operasi API yang digunakan untuk menghasilkan URL yang ditandatangani. Untuk informasi lebih lanjut, lihat Client.presign. |
expires | datetime.timedelta | Periode validitas URL yang ditandatangani. Ini adalah parameter opsional. Misalnya, jika Anda ingin menetapkan periode validitas menjadi 30 menit, atur expires menjadi 30 * time.Minute. Jika Anda tidak menentukan parameter ini, URL yang ditandatangani menggunakan nilai default, yaitu 15 menit. |
expiration | datetime.datetime | Waktu kedaluwarsa absolut URL yang ditandatangani. Ini adalah parameter opsional. |
Jika Anda menggunakan algoritma tanda tangan V4, periode validitas bisa mencapai tujuh hari. Jika Anda menentukan kedua Expiration dan Expires, Expiration akan didahulukan.
Parameter Tanggapan
Tipe | Deskripsi |
PresignResult | Hasil yang dikembalikan, termasuk URL yang ditandatangani, metode HTTP, waktu kedaluwarsa, dan header permintaan yang ditentukan dalam permintaan. Untuk informasi lebih lanjut, lihat PresignResult. |
Parameter tanggapan PresignResult
Parameter | Tipe | Deskripsi |
method | str | Metode HTTP, yang sesuai dengan operasi API. Sebagai contoh, metode HTTP dari operasi PutObject adalah PUT. |
url | str | URL yang ditandatangani. |
expiration | datetime | Waktu kedaluwarsa URL yang ditandatangani. |
signed_headers | MutableMapping | Header yang ditandatangani yang ditentukan dalam permintaan. Sebagai contoh, jika Content-Type ditentukan, informasi tentang Content-Type dikembalikan. |
Untuk informasi lebih lanjut tentang metode presign, kunjungi presign.
Kode Contoh
Hasilkan URL yang ditandatangani untuk mengizinkan permintaan HTTP PUT.
PentingJika Anda menentukan header permintaan saat menghasilkan URL yang ditandatangani untuk permintaan HTTP PUT, pastikan bahwa header permintaan tersebut disertakan dalam permintaan PUT yang dimulai menggunakan URL tersebut. Hal ini mencegah kegagalan permintaan dan kesalahan tanda tangan.
import argparse import requests import alibabacloud_oss_v2 as oss from datetime import datetime, timedelta # Buat parser parameter baris perintah dan jelaskan tujuan skrip. Contoh ini menjelaskan cara menghasilkan URL yang ditandatangani yang mengizinkan permintaan HTTP PUT. parser = argparse.ArgumentParser(description="contoh presign put object") # Tentukan parameter baris perintah, termasuk wilayah, nama bucket, endpoint, dan nama objek yang diperlukan. parser.add_argument('--region', help='Wilayah tempat bucket berada.', required=True) parser.add_argument('--bucket', help='Nama bucket.', required=True) parser.add_argument('--endpoint', help='Nama domain yang dapat digunakan layanan lain untuk mengakses OSS') parser.add_argument('--key', help='Nama objek.', required=True) def main(): # Parsing parameter baris perintah untuk mendapatkan nilai yang ditentukan oleh pengguna. args = parser.parse_args() # Dapatkan kredensial akses dari variabel lingkungan untuk otentikasi. credentials_provider = oss.credentials.EnvironmentVariableCredentialsProvider() # Gunakan konfigurasi default SDK untuk membuat objek konfigurasi dan tentukan penyedia kredensial. cfg = oss.config.load_default() cfg.credentials_provider = credentials_provider # Tentukan atribut wilayah objek konfigurasi berdasarkan parameter baris perintah yang ditentukan oleh pengguna. cfg.region = args.region # Jika endpoint kustom disediakan, modifikasi parameter endpoint dalam objek konfigurasi. if args.endpoint is not None: cfg.endpoint = args.endpoint # Gunakan konfigurasi di atas untuk menginisialisasi instance OSSClient dan izinkan instance tersebut berinteraksi dengan OSS. client = oss.Client(cfg) # Kirim permintaan untuk memulai permintaan PUT dan hasilkan URL yang ditandatangani untuk objek yang ditentukan. pre_result = client.presign(oss.PutObjectRequest( bucket=args.bucket, # Nama bucket. key=args.key, # Nama objek. ),expires=timedelta(seconds=3600)) # Tentukan periode validitas permintaan. Dalam contoh ini, periode validitas diatur menjadi 3.600 detik. # Tampilkan metode, waktu kedaluwarsa, dan URL yang ditandatangani yang ditentukan dalam permintaan untuk memeriksa validitas URL yang ditandatangani. print(f'metode: {pre_result.method},' f' kedaluwarsa: {pre_result.expiration.strftime("%Y-%m-%dT%H:%M:%S.000Z")},' f' url: {pre_result.url}' ) # Tampilkan header yang ditandatangani dalam permintaan, yang disertakan dalam header HTTP saat permintaan dikirim. for key, value in pre_result.signed_headers.items(): print(f'header yang ditandatangani kunci: {key}, header yang ditandatangani nilai: {value}') # Panggil fungsi utama untuk memulai logika pemrosesan saat skrip dijalankan langsung. if __name__ == "__main__": main() # Tentukan titik masuk dalam fungsi skrip. Alur program kontrol dimulai di sini.Gunakan URL yang ditandatangani untuk mengunggah objek.
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; // Ganti <signedUrl> dengan URL otorisasi. URL signedUrl = new URL("<signedUrl>"); // Tentukan jalur lengkap file lokal. Jika Anda tidak menentukan jalur lokal, file diunggah dari jalur yang sesuai dengan proyek program sampel secara 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("Kode status yang dikembalikan:"+response.getStatusLine().getStatusCode()); if(response.getStatusLine().getStatusCode() == 200){ System.out.println("Berhasil diunggah menggunakan library jaringan."); } System.out.println(response.toString()); } catch (Exception e){ e.printStackTrace(); } finally { response.close(); httpClient.close(); } } }Go
package main import ( "fmt" "io" "net/http" "os" ) func uploadFile(signedUrl, filePath string) error { // Buka file. file, err := os.Open(filePath) if err != nil { return fmt.Errorf("Gagal membuka file: %w", err) } defer file.Close() // Buat klien HTTP baru. client := &http.Client{} // Buat permintaan PUT. req, err := http.NewRequest("PUT", signedUrl, file) if err != nil { return fmt.Errorf("Gagal membuat permintaan: %w", err) } // Kirim permintaan. resp, err := client.Do(req) if err != nil { return fmt.Errorf("Gagal mengirim permintaan: %w", err) } defer resp.Body.Close() // Baca tanggapan. body, err := io.ReadAll(resp.Body) if err != nil { return fmt.Errorf("Gagal membaca tanggapan: %w", err) } fmt.Printf("Kode status yang dikembalikan: %d\n", resp.StatusCode) if resp.StatusCode == 200 { fmt.Println("Berhasil diunggah menggunakan library jaringan.") } fmt.Println(string(body)) return nil } func main() { // Ganti <signedUrl> dengan URL otorisasi. signedUrl := "<signedUrl>" // Tentukan jalur lengkap file lokal. Jika Anda tidak menentukan jalur lokal, file diunggah dari jalur yang sesuai dengan proyek program sampel secara default. filePath := "C:\\Users\\demo.txt" err := uploadFile(signedUrl, filePath) if err != nil { fmt.Println("Terjadi kesalahan:", err) } }python
import requests def upload_file(signed_url, file_path): try: # Buka file. with open(file_path, 'rb') as file: # Kirim permintaan PUT untuk mengunggah file. response = requests.put(signed_url, data=file) print(f"Kode status yang dikembalikan: {response.status_code}") if response.status_code == 200: print("Berhasil diunggah menggunakan library jaringan.") print(response.text) except Exception as e: print(f"Terjadi kesalahan: {e}") if __name__ == "__main__": # Ganti <signedUrl> dengan URL otorisasi. signed_url = "<signedUrl>" # Tentukan jalur lengkap file lokal. Jika Anda tidak menentukan jalur lokal, file diunggah dari jalur yang sesuai dengan proyek program sampel secara default. file_path = "C:\\Users\\demo.txt" upload_file(signed_url, file_path)Node.js
const fs = require('fs'); const axios = require('axios'); async function uploadFile(signedUrl, filePath) { try { // Buat aliran baca. const fileStream = fs.createReadStream(filePath); // Kirim permintaan PUT untuk mengunggah file. const response = await axios.put(signedUrl, fileStream, { headers: { 'Content-Type': 'application/octet-stream' // Sesuaikan Content-Type berdasarkan kebutuhan Anda. } }); console.log(`Kode status yang dikembalikan: ${response.status}`); if (response.status === 200) { console.log('Berhasil diunggah menggunakan library jaringan.'); } console.log(response.data); } catch (error) { console.error(`Terjadi kesalahan: ${error.message}`); } } // Fungsi utama. (async () => { // Ganti <signedUrl> dengan URL otorisasi. const signedUrl = '<signedUrl>'; // Tentukan jalur lengkap file lokal. Jika Anda tidak menentukan jalur lokal, file diunggah dari jalur yang sesuai dengan proyek program sampel secara default. const filePath = 'C:\\Users\\demo.txt'; await uploadFile(signedUrl, filePath); })();browser.js
PentingJika Anda menggunakan Browser.js untuk mengunggah file dan mengalami kesalahan 403 SignatureDoesNotMatch, kesalahan ini biasanya terjadi karena browser secara otomatis menambahkan header permintaan Content-Type. Jika header ini tidak ditentukan saat URL yang ditandatangani dihasilkan, verifikasi tanda tangan gagal. Untuk menyelesaikan masalah ini, Anda harus menentukan header permintaan Content-Type saat menghasilkan URL yang ditandatangani.
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Contoh Unggah File</title> </head> <body> <h1>Contoh Unggah File</h1> <!-- Pilih file --> <input type="file" id="fileInput" /> <button id="uploadButton">Unggah File</button> <script> // Ganti ini dengan URL yang ditandatangani yang dihasilkan di Langkah 1. const signedUrl = "<signedUrl>"; document.getElementById('uploadButton').addEventListener('click', async () => { const fileInput = document.getElementById('fileInput'); const file = fileInput.files[0]; if (!file) { alert('Silakan pilih file untuk diunggah.'); return; } try { await upload(file, signedUrl); alert('File berhasil diunggah!'); } catch (error) { console.error('Kesalahan saat unggah:', error); alert('Unggah gagal: ' + error.message); } }); /** * Unggah file ke OSS. * @param {File} file - File yang akan diunggah. * @param {string} presignedUrl - URL yang ditandatangani. */ const upload = async (file, presignedUrl) => { const response = await fetch(presignedUrl, { method: 'PUT', body: file, // Unggah seluruh file. }); if (!response.ok) { throw new Error(`Unggah gagal, status: ${response.status}`); } console.log('File berhasil diunggah'); }; </script> </body> </html>C#
using System.Net.Http.Headers; // Tentukan jalur lengkap file lokal. Jika Anda tidak menentukan jalur lokal, file diunggah dari jalur yang sesuai dengan proyek program sampel secara default. var filePath = "C:\\Users\\demo.txt"; // Ganti <signedUrl> dengan URL otorisasi. var presignedUrl = "<signedUrl>"; // Buat klien HTTP dan buka aliran file lokal. using var httpClient = new HttpClient(); using var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read); using var content = new StreamContent(fileStream); // Buat permintaan PUT. var request = new HttpRequestMessage(HttpMethod.Put, presignedUrl); request.Content = content; // Kirim permintaan. var response = await httpClient.SendAsync(request); // Proses tanggapan. if (response.IsSuccessStatusCode) { Console.WriteLine($"Berhasil diunggah! Kode status: {response.StatusCode}"); Console.WriteLine("Header tanggapan:"); foreach (var header in response.Headers) { Console.WriteLine($"{header.Key}: {string.Join(", ", header.Value)}"); } } else { string responseContent = await response.Content.ReadAsStringAsync(); Console.WriteLine($"Unggah gagal! Kode status: {response.StatusCode}"); Console.WriteLine("Isi tanggapan: " + 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) { // Atur URL. curl_easy_setopt(curl, CURLOPT_URL, signedUrl.c_str()); // Atur metode permintaan ke PUT. curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L); // Buka file. FILE *file = fopen(filePath.c_str(), "rb"); if (!file) { std::cerr << "Gagal membuka file: " << filePath << std::endl; return; } // Dapatkan ukuran file. fseek(file, 0, SEEK_END); long fileSize = ftell(file); fseek(file, 0, SEEK_SET); // Atur ukuran file. curl_easy_setopt(curl, CURLOPT_INFILESIZE_LARGE, (curl_off_t)fileSize); // Atur handle file input. curl_easy_setopt(curl, CURLOPT_READDATA, file); // Eksekusi permintaan. res = curl_easy_perform(curl); if (res != CURLE_OK) { std::cerr << "curl_easy_perform() gagal: " << curl_easy_strerror(res) << std::endl; } else { long httpCode = 0; curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &httpCode); std::cout << "Kode status yang dikembalikan: " << httpCode << std::endl; if (httpCode == 200) { std::cout << "Berhasil diunggah menggunakan library jaringan." << std::endl; } } // Tutup file. fclose(file); // Bersihkan. curl_easy_cleanup(curl); } curl_global_cleanup(); } int main() { // Ganti <signedUrl> dengan URL otorisasi. std::string signedUrl = "<signedUrl>"; // Tentukan jalur lengkap file lokal. Jika Anda tidak menentukan jalur lokal, file diunggah dari jalur yang sesuai dengan proyek program sampel secara 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, "Kode status yang dikembalikan: " + responseCode); if (responseCode == 200) { Log.d(TAG, "Berhasil diunggah menggunakan library jaringan."); } return "Unggah selesai. Kode status: " + responseCode; } catch (IOException e) { e.printStackTrace(); return "Unggah gagal: " + 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(); // Ganti <signedUrl> dengan URL otorisasi. String signedUrl = "<signedUrl>"; // Tentukan jalur lengkap file lokal. Jika Anda tidak menentukan jalur lokal, file diunggah dari jalur yang sesuai dengan proyek program sampel secara default. String filePath = "C:\\Users\\demo.txt"; activity.uploadFile(signedUrl, filePath); } }
Skenario Umum
Tanya Jawab Umum
Ketika saya menggunakan URL yang ditandatangani untuk mengunggah file lokal, apakah file tersebut terunggah jika URL yang ditandatangani kedaluwarsa selama proses unggah?
Jika saya tidak menentukan header permintaan dan metadata pengguna saat menghasilkan URL, apakah saya perlu menentukan header permintaan dan metadata pengguna saat menggunakan URL untuk mengunggah file lokal?
Referensi
Untuk kode contoh lengkap yang digunakan untuk mengunggah objek menggunakan URL yang ditandatangani, kunjungi presigner_put_object.py.
Untuk kode contoh lengkap untuk menggunakan URL yang ditandatangani untuk mengunggah objek menggunakan unggahan multipart, lihat presigner_complete_multipart_upload.py.