Secara default, objek di Bucket OSS bersifat privat. Hanya pemilik objek yang memiliki izin untuk mengunggah objek. Anda dapat menggunakan OSS C# SDK untuk menghasilkan URL yang telah ditandatangani, memungkinkan pengguna lain untuk mengunggah objek. Saat menghasilkan URL yang telah ditandatangani, Anda dapat menentukan waktu kedaluwarsa untuk membatasi durasi akses. URL tersebut dapat digunakan beberapa kali sebelum kedaluwarsa. Jika beberapa operasi unggah dilakukan, objek mungkin akan ditimpa. Setelah URL kedaluwarsa, Anda tidak dapat menggunakannya lagi untuk unggahan dan harus menghasilkan URL baru yang telah ditandatangani.
Precautions
Kode contoh dalam topik ini menggunakan Wilayah China (Hangzhou), dengan ID wilayah
cn-hangzhou, sebagai contoh. Titik akhir publik digunakan secara default. Jika Anda ingin mengakses OSS dari layanan Alibaba Cloud lainnya di wilayah yang sama dengan OSS, gunakan titik akhir internal. Untuk informasi lebih lanjut tentang wilayah dan titik akhir yang didukung oleh OSS, lihat Wilayah dan Titik Akhir OSS.Anda tidak memerlukan izin khusus untuk menghasilkan URL yang ditandatangani. Namun, untuk mengizinkan orang lain menggunakan URL yang ditandatangani untuk mengunggah objek, Anda harus memiliki izin
oss:PutObject. Untuk informasi lebih lanjut, lihat Mengotorisasi Pengguna RAM untuk Mengakses Beberapa Direktori dalam Bucket.
Proses
Gambar berikut menunjukkan cara menggunakan URL yang ditandatangani untuk mengizinkan permintaan HTTP PUT mengunggah objek ke OSS.
Kode contoh
Pemilik objek menghasilkan URL dengan tanda tangan untuk permintaan PUT.
PentingSaat menghasilkan URL dengan tanda tangan untuk permintaan PUT, jika Anda menentukan header permintaan, Anda harus menyertakan header permintaan yang sama saat menggunakan URL dengan tanda tangan untuk memulai permintaan PUT. Jika tidak, permintaan akan gagal dan melaporkan kesalahan ketidakcocokan tanda tangan.
using System.Text; using OSS = AlibabaCloud.OSS.V2; // Buat alias untuk SDK Alibaba Cloud OSS untuk menyederhanakan penggunaan selanjutnya. var region = "cn-hangzhou"; // Diperlukan. Tentukan wilayah tempat bucket berada. Misalnya, jika bucket berada di wilayah China (Hangzhou), atur wilayah menjadi cn-hangzhou. var endpoint = null as string; // Opsional. Tentukan titik akhir yang digunakan untuk mengakses OSS. Misalnya, jika bucket berada di wilayah China (Hangzhou), atur titik akhir menjadi https://oss-cn-hangzhou.aliyuncs.com. var bucket = "nama bucket Anda"; // Diperlukan. Nama bucket. var key = "kunci objek Anda"; // Diperlukan. Nama objek setelah diunggah ke OSS. // Muat konfigurasi default dari SDK OSS. Konfigurasi ini secara otomatis membaca informasi kredensial (seperti AccessKey) dari variabel lingkungan. var cfg = OSS.Configuration.LoadDefault(); // Secara eksplisit konfigurasikan penggunaan variabel lingkungan untuk mendapatkan kredensial untuk verifikasi identitas. Format: OSS_ACCESS_KEY_ID dan OSS_ACCESS_KEY_SECRET. cfg.CredentialsProvider = new OSS.Credentials.EnvironmentVariableCredentialsProvider(); // Atur wilayah bucket dalam konfigurasi. cfg.Region = region; // Jika titik akhir ditentukan, itu akan menimpa titik akhir default. if(endpoint != null) { cfg.Endpoint = endpoint; } // Buat instans klien OSS menggunakan informasi konfigurasi. using var client = new OSS.Client(cfg); // Panggil metode Presign untuk menghasilkan URL dengan tanda tangan. var result = client.Presign(new OSS.Models.PutObjectRequest() { Bucket = bucket, Key = key, }); // Konten untuk diunggah. const string content = "hello oss!"; // Gunakan HttpClient untuk mengunggah konten menggunakan URL dengan tanda tangan. using var hc = new HttpClient(); var httpResult = await hc.PutAsync(result.Url, new ByteArrayContent(Encoding.UTF8.GetBytes(content))); Console.WriteLine("PutObject selesai"); // Cetak pesan yang menunjukkan bahwa operasi selesai. Console.WriteLine($"Kode Status: {httpResult.StatusCode}"); // Kode status HTTP dari tanggapan.Pengguna lain menggunakan URL dengan tanda tangan untuk permintaan 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 dengan tanda tangan. URL signedUrl = new URL("<signedUrl>"); // Tentukan jalur lengkap file lokal yang ingin Anda unggah. Jika jalur file lokal tidak ditentukan, file lokal diunggah dari jalur proyek tempat program sampel berada. 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:"+response.getStatusLine().getStatusCode()); if(response.getStatusLine().getStatusCode() == 200){ System.out.println("Objek diunggah menggunakan pustaka."); } 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 lokal. file, err := os.Open(filePath) if err != nil { return fmt.Errorf("Tidak dapat membuka file lokal: %w", err) } defer file.Close() // Buat klien HTTP. 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 permintaan: %w", err) } fmt.Printf("Kode status: %d\n", resp.StatusCode) if resp.StatusCode == 200 { fmt.Println("Objek diunggah menggunakan pustaka.") } fmt.Println(string(body)) return nil } func main() { // Ganti <signedUrl> dengan URL dengan tanda tangan. signedUrl := "<signedUrl>" // Tentukan jalur lengkap file lokal yang ingin Anda unggah. Jika jalur file lokal tidak ditentukan, file lokal diunggah dari jalur proyek tempat program sampel berada. 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 lokal yang ingin Anda unggah. with open(file_path, 'rb') as file: # Kirim permintaan PUT untuk mengunggah file lokal. response = requests.put(signed_url, data=file) print(f"Kode status: {response.status_code}") if response.status_code == 200: print("Objek diunggah menggunakan pustaka.") print(response.text) except Exception as e: print(f"Terjadi kesalahan: {e}") if __name__ == "__main__": # Ganti <signedUrl> dengan URL dengan tanda tangan yang dihasilkan. signed_url = "<signedUrl>" # Tentukan jalur lengkap file lokal. Jika jalur file lokal tidak ditentukan, file lokal diunggah dari jalur proyek tempat program sampel berada. 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 lokal. const response = await axios.put(signedUrl, fileStream, { headers: { 'Content-Type': 'application/octet-stream' // Tentukan parameter Content-Type. } }); console.log(`Kode status: ${response.status}`); if (response.status === 200) { console.log("Objek diunggah menggunakan pustaka."); } console.log(response.data); } catch (error) { console.error(`Terjadi kesalahan: ${error.message}`); } } // Tentukan fungsi utama. (async () => { // Ganti <signedUrl> dengan URL dengan tanda tangan. const signedUrl = '<signedUrl>'; // Tentukan jalur lengkap file lokal yang ingin Anda unggah. Jika jalur file lokal tidak ditentukan, file lokal diunggah dari jalur proyek tempat program sampel berada. const filePath = 'C:\\Users\\demo.txt'; await uploadFile(signedUrl, filePath); })();browser.js
PentingSaat mengunggah objek menggunakan Browser.js dan URL dengan tanda tangan, kesalahan 403 SignatureNotMatch yang menunjukkan ketidaksesuaian tanda tangan mungkin terjadi. Ini biasanya disebabkan oleh penyertaan otomatis header permintaan Content-Type oleh browser, yang tidak ditentukan saat URL dengan tanda tangan dihasilkan. Untuk mencegah kesalahan ini, pastikan header Content-Type ditentukan saat menghasilkan URL dengan tanda tangan.
<!DOCTYPE html> <html lang="id"> <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 <signedUrl> dengan URL dengan tanda tangan 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 saat mengunggah:', error); alert('Unggah gagal: ' + error.message); } }); /** * Unggah file ke OSS. * @param {File} file - File yang akan diunggah. * @param {string} presignedUrl - URL dengan tanda tangan. */ 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 yang ingin Anda unggah. Jika jalur file lokal tidak ditentukan, file lokal diunggah dari jalur proyek tempat program sampel berada. var filePath = "C:\\Users\\demo.txt"; // Ganti <signedUrl> dengan URL dengan tanda tangan. var presignedUrl = "<signedUrl>"; // Buat klien HTTP dan 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! 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) { // Tentukan URL dengan tanda tangan. curl_easy_setopt(curl, CURLOPT_URL, signedUrl.c_str()); // Setel metode permintaan ke PUT. curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L); // Buka file lokal. FILE *file = fopen(filePath.c_str(), "rb"); if (!file) { std::cerr << "Tidak dapat membuka file: " << filePath << std::endl; return; } // Periksa ukuran file lokal. fseek(file, 0, SEEK_END); long fileSize = ftell(file); fseek(file, 0, SEEK_SET); // Tentukan ukuran file lokal. curl_easy_setopt(curl, CURLOPT_INFILESIZE_LARGE, (curl_off_t)fileSize); // Tentukan 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: " << httpCode << std::endl; if (httpCode == 200) { std::cout << "Objek diunggah menggunakan pustaka jaringan." << std::endl; } } // Tutup file lokal. fclose(file); // Bersihkan handle cURL. curl_easy_cleanup(curl); } curl_global_cleanup(); } int main() { // Ganti <signedUrl> dengan URL dengan tanda tangan. std::string signedUrl = "<signedUrl>"; // Tentukan jalur lengkap file lokal yang ingin Anda unggah. Jika jalur file lokal tidak ditentukan, file lokal diunggah dari jalur proyek tempat program sampel berada. 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: " + responseCode); if (responseCode == 200) { Log.d(TAG, "Objek diunggah menggunakan pustaka."); } return "Objek diunggah. 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 dengan tanda tangan. String signedUrl = "<signedUrl>"; // Tentukan jalur lengkap file lokal yang ingin Anda unggah. Jika jalur file lokal tidak ditentukan, file lokal diunggah dari jalur proyek tempat program sampel berada. String filePath = "C:\\Users\\demo.txt"; activity.uploadFile(signedUrl, filePath); } }
Skenario
FAQ
Jika saya menggunakan tanda tangan sementara untuk mengunggah objek dan tanda tangan tersebut kedaluwarsa selama pengunggahan, apakah pengunggahan gagal?
Jika saya tidak menetapkan header permintaan dan metadata kustom saat saya membuat URL, apakah saya perlu mengonfigurasinya saat menggunakan URL untuk pengunggahan?
Referensi
Untuk kode sampel lengkap yang digunakan untuk mengunggah objek menggunakan URL yang ditandatangani, lihat PresignPutObject.cs.