Secara default, daftar kontrol akses (ACL) dari sebuah objek dalam bucket Object Storage Service (OSS) bersifat pribadi. Hanya pemilik objek yang memiliki izin untuk mengakses objek tersebut. Anda dapat menggunakan OSS SDK for 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 ke bucket berkali-kali. Setelah periode validitas berakhir, pengguna tidak dapat lagi menggunakan URL tersebut untuk mengunggah objek, dan Anda harus menghasilkan URL baru.
Catatan Penggunaan
Dalam topik ini, titik akhir publik wilayah Tiongkok (Hangzhou) digunakan. Untuk mengakses OSS dari layanan Alibaba Cloud lainnya di wilayah yang sama, gunakan titik akhir internal. Untuk detail tentang wilayah dan titik akhir yang didukung, lihat Wilayah dan Titik Akhir.
Dalam topik ini, kredensial akses diperoleh dari variabel lingkungan. Untuk informasi lebih lanjut tentang cara mengonfigurasi kredensial akses, lihat Konfigurasikan Kredensial Akses (Python SDK V1).
Dalam topik ini, instance OSSClient dibuat menggunakan titik akhir OSS. Jika Anda ingin membuat instance OSSClient menggunakan nama domain kustom atau Layanan Token Keamanan (STS), lihat Inisialisasi.
Anda tidak memerlukan izin tertentu 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 Berikan Izin kepada Pengguna RAM Menggunakan Kebijakan Kustom.Dalam topik ini, algoritma tanda tangan V4 digunakan untuk menghasilkan URL yang ditandatangani dengan periode validitas hingga 7 hari. Untuk informasi lebih lanjut, lihat (Direkomendasikan) Tanda tangan V4 dalam URL yang ditandatangani.
Proses
Gambar berikut menunjukkan cara menggunakan URL yang ditandatangani yang mengizinkan permintaan HTTP PUT untuk mengunggah objek ke OSS.
Kode Contoh
Pemilik objek menghasilkan URL yang ditandatangani yang mengizinkan permintaan HTTP PUT.
# -*- coding: utf-8 -*- import oss2 from oss2.credentials import EnvironmentVariableCredentialsProvider # Dapatkan kredensial akses dari variabel lingkungan. Sebelum menjalankan kode contoh, pastikan variabel lingkungan OSS_ACCESS_KEY_ID dan OSS_ACCESS_KEY_SECRET telah dikonfigurasi. auth = oss2.ProviderAuthV4(EnvironmentVariableCredentialsProvider()) # Tentukan titik akhir wilayah tempat bucket berada. Misalnya, jika bucket berada di wilayah Tiongkok (Hangzhou), atur titik akhir menjadi https://oss-cn-hangzhou.aliyuncs.com. endpoint = "https://oss-cn-hangzhou.aliyuncs.com" # Tentukan wilayah tempat bucket berada. Contoh: cn-hangzhou. Parameter ini diperlukan jika Anda menggunakan algoritma tanda tangan V4. region = "cn-hangzhou" # Tentukan nama bucket. bucket = oss2.Bucket(auth, endpoint, "yourBucketName", region=region) # Tentukan jalur lengkap objek. Contoh: exampledir/exampleobject.txt. Jangan sertakan nama bucket dalam jalur lengkap. object_name = 'exampledir/exampleobject.txt' # Hasilkan URL yang ditandatangani yang digunakan untuk mengunggah file lokal. Atur periode validitas URL yang ditandatangani menjadi 60 detik. # Secara default, OSS mengidentifikasi garis miring (/) dalam jalur lengkap objek sebagai karakter escape saat URL yang ditandatangani dihasilkan. Oleh karena itu, Anda tidak dapat langsung menggunakan URL yang ditandatangani. # Atur parameter slash_safe menjadi True. Dengan cara ini, OSS tidak mengidentifikasi garis miring (/) dalam jalur lengkap objek sebagai karakter escape. Dalam hal ini, Anda dapat langsung menggunakan URL yang ditandatangani. url = bucket.sign_url('PUT', object_name, 60, slash_safe=True) print('URL yang ditandatangani:', url)Seorang pengguna menggunakan URL yang ditandatangani yang mengizinkan permintaan HTTP PUT 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 akan diunggah dari jalur yang sesuai dengan proyek program contoh 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("Diunggah berhasil menggunakan pustaka 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("Diunggah berhasil menggunakan pustaka 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 akan diunggah dari jalur yang sesuai dengan proyek program contoh 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("Diunggah berhasil menggunakan pustaka 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 akan diunggah dari jalur yang sesuai dengan proyek program contoh 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('Diunggah berhasil menggunakan pustaka 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 akan diunggah dari jalur yang sesuai dengan proyek program contoh secara default. const filePath = 'C:\\Users\\demo.txt'; await uploadFile(signedUrl, filePath); })();browser.js
PentingJika Anda menggunakan Browser.js untuk mengunggah file dan menemui 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 pada 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 selama 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 akan diunggah dari jalur yang sesuai dengan proyek program contoh 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($"Diunggah berhasil! 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 pegangan 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 << "Diunggah berhasil menggunakan pustaka 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 akan diunggah dari jalur yang sesuai dengan proyek program contoh 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, "Diunggah berhasil menggunakan pustaka 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 akan diunggah dari jalur yang sesuai dengan proyek program contoh secara default. String filePath = "C:\\Users\\demo.txt"; activity.uploadFile(signedUrl, filePath); } }