Secara default, file dalam bucket OSS bersifat privat dan hanya dapat diunggah oleh pemilik bucket. Namun, pemilik bucket dapat menghasilkan URL yang ditandatangani sebelumnya (pre-signed URL) untuk file tertentu guna memberikan izin unggah sementara. Siapa pun yang memiliki URL tersebut dapat mengunggah file selama periode validitasnya. Fitur ini berguna untuk skenario seperti memberi otorisasi kepada mitra untuk mengunggah kontrak atau memungkinkan pengguna mengunggah foto profil.
Perhatian
Pada topik ini, titik akhir publik wilayah China (Hangzhou) digunakan. Untuk mengakses OSS dari layanan Alibaba Cloud lainnya dalam wilayah yang sama, gunakan titik akhir internal. Untuk detail wilayah dan titik akhir yang didukung, lihat Wilayah dan titik akhir.
Izin tidak diperlukan untuk menghasilkan URL yang ditandatangani sebelumnya. Namun, pihak ketiga hanya dapat berhasil mengunggah file menggunakan URL tersebut jika pengguna yang menghasilkan URL memiliki izin
oss:PutObject. Untuk informasi lebih lanjut tentang cara memberikan izin, lihat Berikan izin kustom kepada Pengguna RAM.URL yang ditandatangani sebelumnya tidak mendukung unggahan dalam format FormData. Untuk mengunggah data menggunakan FormData, gunakan unggahan form OSS.
Karena adanya perubahan kebijakan untuk meningkatkan kepatuhan dan keamanan, mulai 20 Maret 2025, pengguna OSS baru harus menggunakan nama domain kustom (CNAME) untuk melakukan operasi API data pada bucket OSS yang berlokasi di wilayah daratan Tiongkok. Titik akhir publik default dibatasi untuk operasi ini. Lihat pengumuman resmi untuk daftar lengkap operasi yang terdampak. Jika Anda mengakses data melalui HTTPS, Anda harus mengikat Sertifikat SSL yang valid ke domain kustom Anda. Hal ini wajib untuk akses Konsol OSS, karena konsol menerapkan HTTPS.
Tinjauan proses
Proses mengunggah file menggunakan URL yang ditandatangani sebelumnya adalah sebagai berikut:
Unggah satu file menggunakan URL yang ditandatangani sebelumnya
Pemilik bucket menghasilkan URL yang ditandatangani sebelumnya untuk permintaan PUT.
CatatanPeriode validitas maksimum URL yang ditandatangani sebelumnya yang dihasilkan menggunakan SDK adalah 7 hari. Jika Anda menggunakan token Security Token Service (STS) untuk menghasilkan URL tersebut, periode validitas maksimumnya adalah 43.200 detik (12 jam).
Java
Untuk informasi lebih lanjut tentang SDK, lihat Unggah file menggunakan URL yang ditandatangani sebelumnya di Java.
import com.aliyun.oss.*; import com.aliyun.oss.common.auth.*; import com.aliyun.oss.common.comm.SignVersion; import com.aliyun.oss.model.GeneratePresignedUrlRequest; import java.net.URL; import java.util.*; import java.util.Date; public class GetSignUrl { public static void main(String[] args) throws Throwable { // Contoh ini menggunakan titik akhir publik wilayah China (Hangzhou). Tentukan titik akhir yang sebenarnya. String endpoint = "https://oss-cn-hangzhou.aliyuncs.com"; // Dapatkan kredensial akses dari variabel lingkungan. Sebelum menjalankan kode contoh, pastikan variabel lingkungan OSS_ACCESS_KEY_ID dan OSS_ACCESS_KEY_SECRET telah dikonfigurasi. EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider(); // Tentukan nama bucket, misalnya examplebucket. String bucketName = "examplebucket"; // Tentukan jalur lengkap objek, misalnya exampleobject.txt. Jalur lengkap objek tidak boleh mengandung nama bucket. String objectName = "exampleobject.txt"; // Tentukan wilayah tempat bucket berada. Misalnya, jika bucket berada di wilayah China (Hangzhou), atur wilayah menjadi cn-hangzhou. String region = "cn-hangzhou"; // Buat instance OSSClient. // Saat instance OSSClient tidak lagi digunakan, panggil metode shutdown untuk melepaskan sumber daya. ClientBuilderConfiguration clientBuilderConfiguration = new ClientBuilderConfiguration(); clientBuilderConfiguration.setSignatureVersion(SignVersion.V4); OSS ossClient = OSSClientBuilder.create() .endpoint(endpoint) .credentialsProvider(credentialsProvider) .clientConfiguration(clientBuilderConfiguration) .region(region) .build(); URL signedUrl = null; try { // Tentukan waktu kedaluwarsa URL yang ditandatangani sebelumnya dalam milidetik. Contoh ini menetapkan waktu kedaluwarsa menjadi 1 jam. Date expiration = new Date(new Date().getTime() + 3600 * 1000L); // Hasilkan URL yang ditandatangani sebelumnya. GeneratePresignedUrlRequest request = new GeneratePresignedUrlRequest(bucketName, objectName, HttpMethod.PUT); // Atur waktu kedaluwarsa. request.setExpiration(expiration); // Hasilkan URL yang ditandatangani sebelumnya untuk permintaan HTTP PUT. signedUrl = ossClient.generatePresignedUrl(request); // Cetak URL yang ditandatangani sebelumnya. System.out.println("signed url for putObject: " + signedUrl); } catch (OSSException oe) { System.out.println("Caught an OSSException, which means your request made it to OSS, " + "but was rejected with an error response for some reason."); System.out.println("Error Message:" + oe.getErrorMessage()); System.out.println("Error Code:" + oe.getErrorCode()); System.out.println("Request ID:" + oe.getRequestId()); System.out.println("Host ID:" + oe.getHostId()); } catch (ClientException ce) { System.out.println("Caught an ClientException, which means the client encountered " + "a serious internal problem while trying to communicate with OSS, " + "such as not being able to access the network."); System.out.println("Error Message:" + ce.getMessage()); } } }Go
Untuk informasi lebih lanjut tentang SDK, lihat Unggah file menggunakan URL yang ditandatangani sebelumnya di Go.
package main import ( "context" "flag" "log" "time" "github.com/aliyun/alibabacloud-oss-go-sdk-v2/oss" "github.com/aliyun/alibabacloud-oss-go-sdk-v2/oss/credentials" ) // Tentukan variabel global. var ( region string // Wilayah tempat bucket berada. bucketName string // Nama bucket. objectName string // Nama objek. ) // Tentukan fungsi init yang digunakan untuk menginisialisasi parameter baris perintah. func init() { flag.StringVar(®ion, "region", "", "The region in which the bucket is located.") flag.StringVar(&bucketName, "bucket", "", "The name of the bucket.") flag.StringVar(&objectName, "object", "", "The name of the object.") } func main() { // Uraikan parameter baris perintah. flag.Parse() // Periksa apakah nama bucket kosong. if len(bucketName) == 0 { flag.PrintDefaults() log.Fatalf("invalid parameters, bucket name required") } // Periksa apakah wilayah kosong. if len(region) == 0 { flag.PrintDefaults() log.Fatalf("invalid parameters, region required") } // Periksa apakah nama objek kosong. if len(objectName) == 0 { flag.PrintDefaults() log.Fatalf("invalid parameters, object name required") } // Muat konfigurasi default dan tentukan penyedia kredensial serta wilayah. cfg := oss.LoadDefaultConfig(). WithCredentialsProvider(credentials.NewEnvironmentVariableCredentialsProvider()). WithRegion(region) // Buat klien OSS. client := oss.NewClient(cfg) // Hasilkan URL yang ditandatangani sebelumnya untuk permintaan PutObject. result, err := client.Presign(context.TODO(), &oss.PutObjectRequest{ Bucket: oss.Ptr(bucketName), Key: oss.Ptr(objectName), //ContentType: oss.Ptr("text/txt"), // Pastikan nilai parameter ContentType yang terdapat dalam URL sama dengan nilai ContentType yang ditentukan dalam permintaan. //Metadata: map[string]string{"key1": "value1", "key2": "value2"}, // Pastikan nilai parameter Metadata yang terdapat dalam URL sama dengan nilai Metadata yang ditentukan dalam permintaan. }, oss.PresignExpires(10*time.Minute), ) if err != nil { log.Fatalf("failed to put object presign %v", err) } log.Printf("request method:%v\n", result.Method) log.Printf("request expiration:%v\n", result.Expiration) log.Printf("request url:%v\n", result.URL) if len(result.SignedHeaders) > 0 { // Jika Anda menentukan header permintaan saat menghasilkan URL yang ditandatangani sebelumnya yang memungkinkan permintaan HTTP PUT, pastikan header permintaan tersebut disertakan dalam permintaan PUT yang diprakarsai menggunakan URL tersebut. log.Printf("signed headers:\n") for k, v := range result.SignedHeaders { log.Printf("%v: %v\n", k, v) } } }Python
Untuk informasi lebih lanjut tentang SDK, lihat Unggah file menggunakan URL yang ditandatangani sebelumnya di Python.
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 sebelumnya yang memungkinkan permintaan HTTP PUT. parser = argparse.ArgumentParser(description="presign put object sample") # Tentukan parameter baris perintah, termasuk wilayah, nama bucket, titik akhir, dan nama objek yang wajib diisi. 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(): # Uraikan parameter baris perintah untuk mendapatkan nilai yang ditentukan pengguna. args = parser.parse_args() # Dapatkan kredensial akses dari variabel lingkungan untuk autentikasi. 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 pengguna. cfg.region = args.region # Jika titik akhir kustom disediakan, ubah parameter titik akhir dalam objek konfigurasi. if args.endpoint is not None: cfg.endpoint = args.endpoint # Gunakan konfigurasi di atas untuk menginisialisasi instance OSSClient dan memungkinkan instance berinteraksi dengan OSS. client = oss.Client(cfg) # Kirim permintaan untuk memprakarsai permintaan PUT dan menghasilkan URL yang ditandatangani sebelumnya 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. Pada contoh ini, periode validitas diatur menjadi 3.600 detik. # Tampilkan metode, waktu kedaluwarsa, dan URL yang ditandatangani sebelumnya yang ditentukan dalam permintaan untuk memeriksa validitas URL tersebut. print(f'method: {pre_result.method},' f' expiration: {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'signed headers key: {key}, signed headers value: {value}') # Panggil fungsi utama untuk memulai logika pemrosesan saat skrip dijalankan secara langsung. if __name__ == "__main__": main() # Tentukan titik masuk dalam fungsi skrip. Alur kontrol program dimulai di sini.Node.js
Bagian ini memberikan contoh skenario umum. Untuk informasi lebih lanjut tentang cara menghasilkan URL yang ditandatangani sebelumnya dengan parameter pemrosesan citra atau ID versi, lihat Unggah file menggunakan URL yang ditandatangani sebelumnya di Node.js.
const OSS = require("ali-oss"); // Definisikan fungsi untuk menghasilkan URL yang ditandatangani. async function generateSignatureUrl(fileName) { // Dapatkan URL yang ditandatangani sebelumnya. const client = await new OSS({ accessKeyId: 'yourAccessKeyId', accessKeySecret: 'yourAccessKeySecret', bucket: 'examplebucket', region: 'oss-cn-hangzhou', authorizationV4: true }); return await client.signatureUrlV4('PUT', 3600, { headers: {} // Atur header permintaan berdasarkan header permintaan aktual. }, fileName); } // Panggil fungsi dan berikan nama file. generateSignatureUrl('yourFileName').then(url => { console.log('Generated Signature URL:', url); }).catch(err => { console.error('Error generating signature URL:', err); });PHP
Bagian ini memberikan contoh skenario umum. Untuk informasi lebih lanjut tentang cara menghasilkan URL yang ditandatangani sebelumnya dengan ID versi, lihat Unggah file menggunakan URL yang ditandatangani sebelumnya di PHP.
<?php if (is_file(__DIR__ . '/../autoload.php')) { require_once __DIR__ . '/../autoload.php'; } if (is_file(__DIR__ . '/../vendor/autoload.php')) { require_once __DIR__ . '/../vendor/autoload.php'; } use OSS\OssClient; use OSS\Core\OssException; use OSS\Http\RequestCore; use OSS\Http\ResponseCore; use OSS\Credentials\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. $provider = new EnvironmentVariableCredentialsProvider(); // Tentukan titik akhir wilayah tempat bucket berada. Misalnya, jika bucket berada di wilayah China (Hangzhou), atur titik akhir menjadi https://oss-cn-hangzhou.aliyuncs.com. $endpoint = "yourEndpoint"; // Tentukan nama bucket. $bucket= "examplebucket"; // Tentukan jalur lengkap objek. Jangan sertakan nama bucket dalam jalur lengkap objek. $object = "exampleobject.txt"; // Atur periode validitas URL yang ditandatangani sebelumnya menjadi 600 detik. Nilai maksimum: 32400. $timeout = 600; try { $config = array( "provider" => $provider, "endpoint" => $endpoint, 'signatureVersion'=>OssClient::OSS_SIGNATURE_VERSION_V4, "region"=> "cn-hangzhou" ); $ossClient = new OssClient($config); // Hasilkan URL yang ditandatangani sebelumnya. $signedUrl = $ossClient->signUrl($bucket, $object, $timeout, "PUT"); print_r($signedUrl); } catch (OssException $e) { printf(__FUNCTION__ . ": FAILED\n"); printf($e->getMessage() . "\n"); return; }Android
Untuk informasi lebih lanjut tentang SDK, lihat Unggah file menggunakan URL yang ditandatangani sebelumnya di Android.
// Tentukan nama bucket, misalnya examplebucket. String bucketName = "examplebucket"; // Tentukan jalur lengkap objek sumber, tanpa nama bucket, misalnya exampleobject.txt. String objectKey = "exampleobject.txt"; // Atur tipe konten. String contentType = "application/octet-stream"; String url = null; try { // Hasilkan URL yang ditandatangani sebelumnya untuk mengunggah file. GeneratePresignedUrlRequest request = new GeneratePresignedUrlRequest(bucketName, objectKey); // Atur waktu kedaluwarsa URL yang ditandatangani sebelumnya menjadi 30 menit. request.setExpiration(30*60); request.setContentType(contentType); request.setMethod(HttpMethod.PUT); url = oss.presignConstrainedObjectURL(request); Log.d("url", url); } catch (ClientException e) { e.printStackTrace(); }C++
Untuk informasi lebih lanjut tentang SDK, lihat Unggah file menggunakan URL yang ditandatangani sebelumnya di C++.
#include <alibabacloud/oss/OssClient.h> using namespace AlibabaCloud::OSS; int main(void) { /* Inisialisasi informasi akun yang digunakan untuk mengakses OSS. */ /* Tentukan titik akhir wilayah tempat bucket berada. Misalnya, jika bucket berada di wilayah China (Hangzhou), atur titik akhir menjadi https://oss-cn-hangzhou.aliyuncs.com. */ std::string Endpoint = "yourEndpoint"; /* Tentukan wilayah tempat bucket berada. Misalnya, jika bucket berada di wilayah China (Hangzhou), atur wilayah menjadi cn-hangzhou. * / std::string Region = "yourRegion"; /* Tentukan nama bucket. Contoh: examplebucket. */ std::string BucketName = "examplebucket"; /* Tentukan jalur lengkap objek. Jangan sertakan nama bucket dalam jalur lengkap. Contoh: exampledir/exampleobject.txt. */ std::string PutobjectUrlName = "exampledir/exampleobject.txt"; /* Inisialisasi sumber daya, seperti sumber daya jaringan. */ InitializeSdk(); ClientConfiguration conf; conf.signatureVersion = SignatureVersionType::V4; /* Dapatkan kredensial akses dari variabel lingkungan. Sebelum menjalankan kode contoh, pastikan variabel lingkungan OSS_ACCESS_KEY_ID dan OSS_ACCESS_KEY_SECRET telah dikonfigurasi. */ auto credentialsProvider = std::make_shared<EnvironmentVariableCredentialsProvider>(); OssClient client(Endpoint, credentialsProvider, conf); client.SetRegion(Region); /* Tentukan periode validitas URL yang ditandatangani sebelumnya. Periode validitas maksimum adalah 32.400. Satuan: detik. */ std::time_t t = std::time(nullptr) + 1200; /* Hasilkan URL yang ditandatangani sebelumnya. */ auto genOutcome = client.GeneratePresignedUrl(BucketName, PutobjectUrlName, t, Http::Put); if (genOutcome.isSuccess()) { std::cout << "GeneratePresignedUrl success, Gen url:" << genOutcome.result().c_str() << std::endl; } else { /* Tangani pengecualian. */ std::cout << "GeneratePresignedUrl fail" << ",code:" << genOutcome.error().Code() << ",message:" << genOutcome.error().Message() << ",requestId:" << genOutcome.error().RequestId() << std::endl; return -1; } /* Lepaskan sumber daya, seperti sumber daya jaringan. */ ShutdownSdk(); return 0; }iOS
Untuk informasi lebih lanjut tentang SDK, lihat Unggah file menggunakan URL yang ditandatangani sebelumnya di iOS.
// Tentukan nama bucket. NSString *bucketName = @"examplebucket"; // Tentukan nama objek. NSString *objectKey = @"exampleobject.txt"; NSURL *file = [NSURL fileURLWithPath:@"<filePath>"]; NSString *contentType = [OSSUtil detemineMimeTypeForFilePath:file.absoluteString uploadName:objectKey]; __block NSString *urlString; // Hasilkan URL yang ditandatangani sebelumnya dengan periode validitas untuk mengunggah objek. Pada contoh ini, periode validitas URL adalah 30 menit. OSSTask *task = [client presignConstrainURLWithBucketName:bucketName withObjectKey:objectKey httpMethod:@"PUT" withExpirationInterval:30 * 60 withParameters:@{} contentType:contentType contentMd5:nil]; [task continueWithBlock:^id _Nullable(OSSTask * _Nonnull task) { if (task.error) { NSLog(@"presign error: %@", task.error); } else { urlString = task.result; NSLog(@"url: %@", urlString); } return nil; }];.NET
Untuk informasi lebih lanjut tentang SDK, lihat Unggah file menggunakan URL yang ditandatangani sebelumnya di .NET.
using Aliyun.OSS; using Aliyun.OSS.Common; // Tentukan Titik Akhir untuk wilayah tempat bucket berada. Misalnya, jika bucket berada di wilayah China (Hangzhou), atur Titik Akhir menjadi https://oss-cn-hangzhou.aliyuncs.com. var endpoint = "https://oss-cn-hangzhou.aliyuncs.com"; // Dapatkan kredensial akses dari variabel lingkungan. Sebelum menjalankan kode ini, pastikan variabel lingkungan OSS_ACCESS_KEY_ID dan OSS_ACCESS_KEY_SECRET telah dikonfigurasi. var accessKeyId = Environment.GetEnvironmentVariable("OSS_ACCESS_KEY_ID"); var accessKeySecret = Environment.GetEnvironmentVariable("OSS_ACCESS_KEY_SECRET"); // Tentukan nama bucket, misalnya examplebucket. var bucketName = "examplebucket"; // Tentukan jalur lengkap objek. Jalur lengkap tidak mencakup nama bucket. Misalnya, exampledir/exampleobject.txt. var objectName = "exampledir/exampleobject.txt"; var objectContent = "More than just cloud."; // Tentukan wilayah tempat bucket berada. Misalnya, jika bucket berada di wilayah China (Hangzhou), atur wilayah menjadi cn-hangzhou. const string region = "cn-hangzhou"; // Buat instance ClientConfiguration dan ubah parameter default sesuai kebutuhan. var conf = new ClientConfiguration(); // Atur versi tanda tangan menjadi V4. conf.SignatureVersion = SignatureVersion.V4; // Buat instance OssClient. var client = new OssClient(endpoint, accessKeyId, accessKeySecret, conf); client.SetRegion(region); try { // Hasilkan URL yang ditandatangani. var generatePresignedUriRequest = new GeneratePresignedUriRequest(bucketName, objectName, SignHttpMethod.Put) { // Atur waktu kedaluwarsa URL yang ditandatangani. Nilai default adalah 3600 detik. Expiration = DateTime.Now.AddHours(1), }; var signedUrl = client.GeneratePresignedUri(generatePresignedUriRequest); } catch (OssException ex) { Console.WriteLine("Failed with error code: {0}; Error info: {1}. \nRequestID:{2}\tHostID:{3}", ex.ErrorCode, ex.Message, ex.RequestId, ex.HostId); } catch (Exception ex) { Console.WriteLine("Failed with error info: {0}", ex.Message); }C
Untuk informasi lebih lanjut tentang SDK, lihat Unduh file menggunakan URL yang ditandatangani sebelumnya di C.
#include "oss_api.h" #include "aos_http_io.h" /* Atur yourEndpoint ke titik akhir wilayah tempat bucket berada. Misalnya, jika bucket berada di wilayah China (Hangzhou), atur titik akhir menjadi https://oss-cn-hangzhou.aliyuncs.com. */ const char *endpoint = "yourEndpoint"; /* Tentukan nama bucket. Misalnya, examplebucket. */ const char *bucket_name = "examplebucket"; /* Tentukan jalur lengkap objek. Jalur lengkap tidak boleh mengandung nama bucket. Misalnya, exampledir/exampleobject.txt. */ const char *object_name = "exampledir/exampleobject.txt"; /* Tentukan jalur lengkap file lokal. */ const char *local_filename = "yourLocalFilename"; void init_options(oss_request_options_t *options) { options->config = oss_config_create(options->pool); /* Inisialisasi tipe aos_string_t dengan string char*. */ aos_str_set(&options->config->endpoint, endpoint); /* Dapatkan kredensial akses dari variabel lingkungan. Sebelum menjalankan kode contoh ini, pastikan variabel lingkungan OSS_ACCESS_KEY_ID dan OSS_ACCESS_KEY_SECRET telah diatur. */ aos_str_set(&options->config->access_key_id, getenv("OSS_ACCESS_KEY_ID")); aos_str_set(&options->config->access_key_secret, getenv("OSS_ACCESS_KEY_SECRET")); /* Tentukan apakah akan menggunakan CNAME untuk mengakses OSS. Nilai 0 menunjukkan bahwa CNAME tidak digunakan. */ options->config->is_cname = 0; /* Atur parameter jaringan, seperti periode timeout. */ options->ctl = aos_http_controller_create(options->pool, 0); } int main(int argc, char *argv[]) { /* Panggil metode aos_http_io_initialize di entri program untuk menginisialisasi sumber daya global, seperti jaringan dan memori. */ if (aos_http_io_initialize(NULL, 0) != AOSE_OK) { exit(1); } /* Pool memori (pool) untuk manajemen memori, yang setara dengan apr_pool_t. Kode implementasinya ada di pustaka APR. */ aos_pool_t *pool; /* Buat pool memori baru. Parameter kedua adalah NULL, yang menunjukkan bahwa pool tidak mewarisi dari pool memori lain. */ aos_pool_create(&pool, NULL); /* Buat dan inisialisasi opsi. Parameter ini mencakup informasi konfigurasi global, seperti endpoint, access_key_id, access_key_secret, is_cname, dan curl. */ oss_request_options_t *oss_client_options; /* Alokasikan memori untuk opsi dalam pool memori. */ oss_client_options = oss_request_options_create(pool); /* Inisialisasi opsi klien oss_client_options. */ init_options(oss_client_options); /* Inisialisasi parameter. */ aos_string_t bucket; aos_string_t object; aos_string_t file; aos_http_request_t *req; apr_time_t now; char *url_str; aos_string_t url; int64_t expire_time; int one_hour = 3600; aos_str_set(&bucket, bucket_name); aos_str_set(&object, object_name); aos_str_set(&file, local_filename); expire_time = now / 1000000 + one_hour; req = aos_http_request_create(pool); req->method = HTTP_PUT; now = apr_time_now(); /* Satuan: mikrodetik. */ expire_time = now / 1000000 + one_hour; /* Hasilkan URL yang ditandatangani sebelumnya. */ url_str = oss_gen_signed_url(oss_client_options, &bucket, &object, expire_time, req); aos_str_set(&url, url_str); printf("Temporary upload URL: %s\n", url_str); /* Lepaskan pool memori. Ini setara dengan melepaskan memori yang dialokasikan untuk berbagai sumber daya selama permintaan. */ aos_pool_destroy(pool); /* Lepaskan sumber daya global yang sebelumnya dialokasikan. */ aos_http_io_deinitialize(); return 0; }
Pihak ketiga menggunakan URL yang ditandatangani sebelumnya yang dihasilkan untuk mengunggah file dengan permintaan PUT.
PentingURL yang ditandatangani sebelumnya dapat diakses beberapa kali sebelum kedaluwarsa. Namun, melakukan beberapa operasi unggahan menimbulkan risiko menimpa file. Setelah URL kedaluwarsa, Anda harus mengikuti Langkah 1 untuk menghasilkan ulang URL yang ditandatangani sebelumnya agar dapat terus mengakses file.
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 yang diotorisasi. URL signedUrl = new URL("<signedUrl>"); // Tentukan jalur lengkap file lokal. Jika Anda tidak menentukan jalur lokal, file diunggah dari jalur 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("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 { 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("Unable to open 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("Failed to create request: %w", err) } // Kirim permintaan. resp, err := client.Do(req) if err != nil { return fmt.Errorf("Failed to send request: %w", err) } defer resp.Body.Close() // Baca respons. 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() { // Ganti <signedUrl> dengan URL yang diotorisasi. signedUrl := "<signedUrl>" // Tentukan jalur lengkap file lokal. Jika Anda tidak menentukan jalur lokal, file diunggah dari jalur proyek program contoh secara 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: # Buka file. with open(file_path, 'rb') as file: # Kirim permintaan PUT untuk mengunggah 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__": # Ganti <signedUrl> dengan URL yang diotorisasi. signed_url = "<signedUrl>" // Tentukan jalur lengkap file lokal. Jika Anda tidak menentukan jalur lokal, file diunggah dari jalur 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 sesuai kebutuhan. } }); 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}`); } } // Fungsi utama. (async () => { // Ganti <signedUrl> dengan URL yang diotorisasi. const signedUrl = '<signedUrl>'; // Tentukan jalur lengkap file lokal. Jika Anda tidak menentukan jalur lokal, file diunggah dari jalur proyek program contoh secara default. const filePath = 'C:\\Users\\demo.txt'; await uploadFile(signedUrl, filePath); })();browser.js
PentingJika Anda mengalami kesalahan ketidakcocokan tanda tangan 403 saat menggunakan Browser.js untuk mengunggah file, biasanya karena browser secara otomatis menambahkan header permintaan Content-Type, tetapi header ini tidak ditentukan saat URL yang ditandatangani sebelumnya dihasilkan. Hal ini menyebabkan kegagalan verifikasi tanda tangan. Untuk mengatasi masalah ini, Anda harus menentukan header permintaan Content-Type saat menghasilkan URL yang ditandatangani sebelumnya.
<!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> <!-- Pilih file --> <input type="file" id="fileInput" /> <button id="uploadButton">Upload File</button> <script> // Ganti ini dengan URL yang ditandatangani sebelumnya 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('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); } }); /** * Unggah file ke OSS. * @param {File} file - File yang akan diunggah. * @param {string} presignedUrl - URL yang ditandatangani sebelumnya. */ const upload = async (file, presignedUrl) => { const response = await fetch(presignedUrl, { method: 'PUT', body: file, // Unggah seluruh file secara langsung. }); 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; // Tentukan jalur lengkap file lokal. Jika Anda tidak menentukan jalur lokal, file diunggah dari jalur proyek program contoh secara default. var filePath = "C:\\Users\\demo.txt"; // Ganti <signedUrl> dengan URL yang diotorisasi. 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 respons. 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) { // Atur URL. curl_easy_setopt(curl, CURLOPT_URL, signedUrl.c_str()); // Atur metode permintaan menjadi PUT. curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L); // Buka file. FILE *file = fopen(filePath.c_str(), "rb"); if (!file) { std::cerr << "Unable to open 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() 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; } } // Tutup file. fclose(file); // Bersihkan. curl_easy_cleanup(curl); } curl_global_cleanup(); } int main() { // Ganti <signedUrl> dengan URL yang diotorisasi. std::string signedUrl = "<signedUrl>"; // Tentukan jalur lengkap file lokal. Jika Anda tidak menentukan jalur lokal, file diunggah dari jalur 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, "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(); // Ganti <signedUrl> dengan URL yang diotorisasi. String signedUrl = "<signedUrl>"; // Tentukan jalur lengkap file lokal. Jika Anda tidak menentukan jalur lokal, file diunggah dari jalur proyek program contoh secara default. String filePath = "C:\\Users\\demo.txt"; activity.uploadFile(signedUrl, filePath); } }
Lakukan unggah multi-bagian menggunakan URL yang ditandatangani sebelumnya
Jika klien tidak dapat diintegrasikan dengan SDK OSS tetapi perlu mengunggah file besar, Anda dapat menggunakan URL yang ditandatangani sebelumnya untuk melakukan unggah multi-bagian. Dalam metode ini, server memprakarsai tugas unggahan dan menghasilkan URL yang ditandatangani sebelumnya dengan izin untuk setiap bagian. Klien atau aplikasi pihak ketiga kemudian menggunakan URL tersebut untuk mengunggah bagian-bagian tersebut. Setelah semua bagian diunggah, server memprakarsai permintaan untuk menggabungkan bagian-bagian tersebut menjadi satu file lengkap.
Unggah multi-bagian yang menggunakan URL yang ditandatangani sebelumnya relatif kompleks. Klien harus mengunggah bagian yang benar untuk `partNumber` yang ditentukan dalam URL. Bagian yang hilang atau tidak cocok menghasilkan file akhir yang salah. Oleh karena itu, jika klien Anda dapat diintegrasikan dengan SDK OSS, kami merekomendasikan agar Anda menggunakan otorisasi STS untuk mengimplementasikan unggahan langsung dari sisi klien. Metode ini lebih sederhana untuk dikembangkan dan menyediakan unggahan yang lebih stabil.
Klien memprakarsai permintaan unggahan
Klien mengirim permintaan unggahan ke server yang berisi nama file, ukuran file, dan ukuran bagian yang diinginkan. Ukuran bagian tidak boleh melebihi 5 GB. Ukuran bagian 5 MB direkomendasikan.
Contoh berikut menunjukkan permintaan. Dalam contoh ini,
https://yourserver.com/init-uploadadalah titik akhir API inisialisasi yang disediakan oleh server Anda. Gantilah dengan titik akhir yang sebenarnya.curl -X POST https://yourserver.com/init-upload \ -H "Content-Type: application/json" \ -d '{ "fileName": "exampleobject.jpg", "fileSize": 104857600, "partSize": 5242880 }'Server memprakarsai tugas unggahan dan menghasilkan URL yang ditandatangani sebelumnya
Panggil operasi InitiateMultipartUpload untuk menginisialisasi tugas unggahan dan mendapatkan UploadId.
Hitung jumlah bagian berdasarkan ukuran file dan ukuran bagian yang diinginkan.
Hasilkan URL yang ditandatangani sebelumnya yang sesuai untuk setiap bagian.
Kembalikan daftar URL dalam format JSON.
CatatanServer harus mencatat UploadId dan memastikan bahwa UploadId tersebut memiliki pemetaan unik ke file yang diunggah. Hal ini diperlukan untuk verifikasi dan penggabungan bagian selanjutnya. Anda dapat menggunakan cache atau database untuk menyimpan UploadId sesuai kebutuhan.
Klien mengunggah data bagian
Klien menggunakan daftar URL yang ditandatangani sebelumnya yang dikembalikan oleh server untuk mengunggah setiap bagian menggunakan permintaan HTTP PUT. Metodenya sama dengan mengunggah satu file. Setelah semua bagian diunggah, klien harus memberi tahu server untuk memprakarsai operasi penggabungan.
CatatanUnggahan konkuren didukung. Namun, Anda harus memastikan bahwa konten yang diunggah menggunakan setiap URL sesuai dengan bagian yang benar. Artinya, untuk URL dengan `partNumber=N`, Anda hanya dapat mengunggah bagian ke-N dari file. Anda tidak boleh mencampur atau melewatkan bagian.
Contoh berikut menunjukkan cara mengunggah bagian pertama. /path/to/local/file adalah jalur bagian lokal.
curl -X PUT -T /path/to/local/file "https://examplebucket.oss-cn-hangzhou.aliyuncs.com/exampleobject.jpg?partNumber=1&uploadId=BE2D0BC931BE4DE1B23F339AABFA49EE&x-oss-credential=LTAI********************%2F20250520%2Fcn-hangzhou%2Foss%2Faliyun_v4_request&x-oss-date=20250520T082728Z&x-oss-expires=3600&x-oss-signature=81f3d2e5eaa67c432291577ed20af3b3f60df05ab3cddedcdce168ef707f7ad0&x-oss-signature-version=OSS4-HMAC-SHA256"(Opsional) Server memverifikasi bagian yang diunggah
Setelah server menerima notifikasi "unggahan selesai", server dapat memanggil operasi ListParts untuk memverifikasi hal berikut:
Apakah jumlah bagian lengkap.
Apakah ukuran setiap bagian sesuai harapan.
CatatanOperasi ini menggunakan UploadId yang sebelumnya dicatat.
Server menggabungkan bagian dan mengembalikan hasil
Setelah verifikasi berhasil, server memanggil operasi CompleteMultipartUpload untuk menggabungkan bagian dan mengembalikan hasil unggahan kepada klien.
Atur header untuk menentukan kebijakan unggahan
Saat Anda menghasilkan URL yang ditandatangani sebelumnya, Anda dapat menentukan parameter header untuk menentukan kebijakan unggahan. Misalnya, Anda dapat mengatur kelas penyimpanan file x-oss-storage-class dan tipe konten Content-Type, seperti yang ditunjukkan dalam contoh kode berikut.
Jika Anda menentukan parameter header saat menghasilkan URL yang ditandatangani sebelumnya, Anda juga harus meneruskan header yang sama saat menggunakan URL tersebut untuk mengunggah file. Jika tidak, OSS akan mengembalikan kesalahan 403 karena verifikasi tanda tangan gagal.
Untuk informasi lebih lanjut tentang header sistem OSS yang dapat Anda atur, lihat PutObject. Anda juga dapat mengatur header kustom untuk mengelola file. Untuk informasi lebih lanjut, lihat Kelola metadata file.
Pemilik bucket menghasilkan URL yang ditandatangani sebelumnya dengan parameter header.
Java
import com.aliyun.oss.*; import com.aliyun.oss.common.auth.*; import com.aliyun.oss.common.comm.SignVersion; import com.aliyun.oss.internal.OSSHeaders; import com.aliyun.oss.model.GeneratePresignedUrlRequest; import com.aliyun.oss.model.StorageClass; import java.net.URL; import java.util.*; import java.util.Date; public class GetSignUrl { public static void main(String[] args) throws Throwable { // Contoh ini menggunakan titik akhir publik wilayah China (Hangzhou). Tentukan titik akhir yang sebenarnya. String endpoint = "https://oss-cn-hangzhou.aliyuncs.com"; // Dapatkan kredensial akses dari variabel lingkungan. Sebelum menjalankan kode contoh, pastikan variabel lingkungan OSS_ACCESS_KEY_ID dan OSS_ACCESS_KEY_SECRET telah dikonfigurasi. EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider(); // Tentukan nama bucket, misalnya examplebucket. String bucketName = "examplebucket"; // Tentukan jalur lengkap objek, misalnya exampleobject.txt. Jalur lengkap objek tidak boleh mengandung nama bucket. String objectName = "exampleobject.txt"; // Tentukan wilayah tempat bucket berada. Misalnya, jika bucket berada di wilayah China (Hangzhou), atur wilayah menjadi cn-hangzhou. String region = "cn-hangzhou"; // Buat instance OSSClient. // Saat instance OSSClient tidak lagi digunakan, panggil metode shutdown untuk melepaskan sumber daya. ClientBuilderConfiguration clientBuilderConfiguration = new ClientBuilderConfiguration(); clientBuilderConfiguration.setSignatureVersion(SignVersion.V4); OSS ossClient = OSSClientBuilder.create() .endpoint(endpoint) .credentialsProvider(credentialsProvider) .clientConfiguration(clientBuilderConfiguration) .region(region) .build(); // Atur header permintaan. Map<String, String> headers = new HashMap<String, String>(); // Tentukan StorageClass. headers.put(OSSHeaders.STORAGE_CLASS, StorageClass.Standard.toString()); // Tentukan ContentType. headers.put(OSSHeaders.CONTENT_TYPE, "text/plain; charset=utf8"); // Atur metadata pengguna kustom. Map<String, String> userMetadata = new HashMap<String, String>(); userMetadata.put("key1","value1"); userMetadata.put("key2","value2"); URL signedUrl = null; try { // Tentukan waktu kedaluwarsa URL yang ditandatangani sebelumnya dalam milidetik. Contoh ini menetapkan waktu kedaluwarsa menjadi 1 jam. Date expiration = new Date(new Date().getTime() + 3600 * 1000L); // Hasilkan URL yang ditandatangani sebelumnya. GeneratePresignedUrlRequest request = new GeneratePresignedUrlRequest(bucketName, objectName, HttpMethod.PUT); // Atur waktu kedaluwarsa. request.setExpiration(expiration); // Tambahkan header permintaan ke permintaan. request.setHeaders(headers); // Tambahkan metadata pengguna kustom. request.setUserMetadata(userMetadata); // Hasilkan URL yang ditandatangani sebelumnya untuk permintaan HTTP PUT. signedUrl = ossClient.generatePresignedUrl(request); // Cetak URL yang ditandatangani sebelumnya. System.out.println("signed url for putObject: " + signedUrl); } catch (OSSException oe) { System.out.println("Caught an OSSException, which means your request made it to OSS, " + "but was rejected with an error response for some reason."); System.out.println("Error Message:" + oe.getErrorMessage()); System.out.println("Error Code:" + oe.getErrorCode()); System.out.println("Request ID:" + oe.getRequestId()); System.out.println("Host ID:" + oe.getHostId()); } catch (ClientException ce) { System.out.println("Caught an ClientException, which means the client encountered " + "a serious internal problem while trying to communicate with OSS, " + "such as not being able to access the network."); System.out.println("Error Message:" + ce.getMessage()); } } }Go
package main import ( "context" "flag" "log" "time" "github.com/aliyun/alibabacloud-oss-go-sdk-v2/oss" "github.com/aliyun/alibabacloud-oss-go-sdk-v2/oss/credentials" ) // Definisikan variabel global. var ( region string // Wilayah tempat bucket berada. bucketName string // Nama bucket. objectName string // Nama objek. ) // Tentukan fungsi init yang digunakan untuk menginisialisasi parameter baris perintah. func init() { flag.StringVar(®ion, "region", "", "The region in which the bucket is located.") flag.StringVar(&bucketName, "bucket", "", "The name of the bucket.") flag.StringVar(&objectName, "object", "", "The name of the object.") } func main() { // Uraikan parameter baris perintah. flag.Parse() // Periksa apakah nama bucket ditentukan. if len(bucketName) == 0 { flag.PrintDefaults() log.Fatalf("invalid parameters, bucket name required") } // Periksa apakah wilayah ditentukan. if len(region) == 0 { flag.PrintDefaults() log.Fatalf("invalid parameters, region required") } // Periksa apakah nama objek ditentukan. if len(objectName) == 0 { flag.PrintDefaults() log.Fatalf("invalid parameters, object name required") } // Muat konfigurasi default dan tentukan penyedia kredensial serta wilayah. cfg := oss.LoadDefaultConfig(). WithCredentialsProvider(credentials.NewEnvironmentVariableCredentialsProvider()). WithRegion(region) // Buat klien OSS. client := oss.NewClient(cfg) // Hasilkan URL yang ditandatangani sebelumnya untuk permintaan PutObject. result, err := client.Presign(context.TODO(), &oss.PutObjectRequest{ Bucket: oss.Ptr(bucketName), Key: oss.Ptr(objectName), ContentType: oss.Ptr("text/plain;charset=utf8"), // Pastikan nilai parameter ContentType yang terdapat dalam URL sama dengan nilai ContentType yang ditentukan dalam permintaan. StorageClass: oss.StorageClassStandard, // Pastikan nilai parameter StorageClass yang terdapat dalam URL sama dengan nilai StorageClass yang ditentukan dalam permintaan. Metadata: map[string]string{"key1": "value1", "key2": "value2"}, // Pastikan nilai Metadata yang terdapat dalam URL sama dengan nilai Metadata yang ditentukan dalam permintaan. }, oss.PresignExpires(10*time.Minute), ) if err != nil { log.Fatalf("failed to put object presign %v", err) } log.Printf("request method:%v\n", result.Method) log.Printf("request expiration:%v\n", result.Expiration) log.Printf("request url:%v\n", result.URL) if len(result.SignedHeaders) > 0 { // Jika Anda menentukan header permintaan saat menghasilkan URL yang ditandatangani sebelumnya yang memungkinkan permintaan HTTP PUT, pastikan header permintaan tersebut disertakan dalam permintaan PUT yang diprakarsai menggunakan URL tersebut. log.Printf("signed headers:\n") for k, v := range result.SignedHeaders { log.Printf("%v: %v\n", k, v) } } }Python
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 sebelumnya yang memungkinkan permintaan HTTP PUT. parser = argparse.ArgumentParser(description="presign put object sample") # Tentukan parameter baris perintah, termasuk wilayah, nama bucket, titik akhir, dan nama objek yang wajib diisi. 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(): # Uraikan parameter baris perintah untuk mendapatkan nilai yang ditentukan pengguna. args = parser.parse_args() # Dapatkan kredensial akses dari variabel lingkungan untuk autentikasi. 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 pengguna. cfg.region = args.region # Jika titik akhir kustom disediakan, ubah parameter titik akhir dalam objek konfigurasi. if args.endpoint is not None: cfg.endpoint = args.endpoint # Gunakan konfigurasi di atas untuk menginisialisasi instance OSSClient dan memungkinkan instance berinteraksi dengan OSS. client = oss.Client(cfg) # Kirim permintaan untuk memprakarsai permintaan PUT dan menghasilkan URL yang ditandatangani sebelumnya untuk objek yang ditentukan. pre_result = client.presign(oss.PutObjectRequest( bucket=args.bucket, # Nama bucket. key=args.key, # Nama objek. content_type='text/plain;charset=utf8', # Tentukan tipe objek. storage_class='Standard', # Tentukan kelas penyimpanan objek. metadata={ 'key1': 'value1', # Tentukan metadata objek. 'key2': 'value2' # Tentukan metadata objek. } ),expires=timedelta(seconds=3600)) # Tentukan periode validitas permintaan. Pada contoh ini, periode validitas diatur menjadi 3.600 detik. # Tampilkan metode, waktu kedaluwarsa, dan URL yang ditandatangani sebelumnya yang ditentukan dalam permintaan untuk memeriksa validitas URL tersebut. print(f'method: {pre_result.method},' f' expiration: {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'signed headers key: {key}, signed headers value: {value}') # Panggil fungsi utama untuk memulai logika pemrosesan saat skrip dijalankan secara langsung. if __name__ == "__main__": main() # Tentukan titik masuk dalam fungsi skrip. Alur kontrol program dimulai di sini.Pihak ketiga menggunakan URL yang ditandatangani sebelumnya untuk mengunggah file dan meneruskan header yang sama.
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
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; // Ganti <signedUrl> dengan URL yang diotorisasi. URL signedUrl = new URL("<signedUrl>"); // Tentukan jalur lengkap file lokal. Jika Anda tidak menentukan jalur lokal, file diunggah dari jalur proyek program contoh secara default. String pathName = "C:\\Users\\demo.txt"; // Atur header permintaan. Informasi header permintaan harus sama dengan informasi yang digunakan saat URL dihasilkan. Map<String, String> headers = new HashMap<String, String>(); //Tentukan kelas penyimpanan objek. headers.put(OSSHeaders.STORAGE_CLASS, StorageClass.Standard.toString()); //Tentukan ContentType. headers.put(OSSHeaders.CONTENT_TYPE, "text/plain;charset=utf8"); // Atur metadata pengguna kustom. Metadata pengguna kustom harus sama dengan informasi yang digunakan saat URL dihasilkan. 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); // Jika Anda mengatur parameter header, seperti metadata pengguna dan kelas penyimpanan, saat menghasilkan URL yang ditandatangani sebelumnya, Anda juga harus mengirim parameter ini ke server saat menggunakan URL tersebut untuk mengunggah file. Kesalahan tanda tangan akan dilaporkan jika parameter yang dikirim ke server tidak konsisten dengan parameter yang ditandatangani. for(Map.Entry header: headers.entrySet()){ put.addHeader(header.getKey().toString(),header.getValue().toString()); } for(Map.Entry meta: userMetadata.entrySet()){ // Jika Anda menggunakan userMeta, SDK secara internal menambahkan awalan 'x-oss-meta-'. Saat Anda menggunakan metode lain untuk menghasilkan URL yang ditandatangani sebelumnya untuk unggahan, Anda juga harus menambahkan awalan 'x-oss-meta-' ke userMeta. put.addHeader("x-oss-meta-"+meta.getKey().toString(), meta.getValue().toString()); } 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 { response.close(); 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 { // Buka file. file, err := os.Open(filePath) if err != nil { return err } defer file.Close() // Baca konten file. fileBytes, err := ioutil.ReadAll(file) if err != nil { return err } // Buat permintaan. req, err := http.NewRequest("PUT", signedUrl, bytes.NewBuffer(fileBytes)) if err != nil { return err } // Atur header permintaan. for key, value := range headers { req.Header.Set(key, value) } // Atur metadata pengguna kustom. for key, value := range metadata { req.Header.Set(fmt.Sprintf("x-oss-meta-%s", key), value) } // Kirim permintaan. client := &http.Client{} resp, err := client.Do(req) if err != nil { return err } defer resp.Body.Close() // Proses respons. 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() { // Ganti <signedUrl> dengan URL yang diotorisasi. signedUrl := "<signedUrl>" // Tentukan jalur lengkap file lokal. Jika Anda tidak menentukan jalur lokal, file diunggah dari jalur proyek program contoh secara default. filePath := "C:\\Users\\demo.txt" // Atur header permintaan. Informasi header permintaan harus sama dengan informasi yang digunakan saat URL dihasilkan. headers := map[string]string{ "Content-Type": "text/plain;charset=utf8", "x-oss-storage-class": "Standard", } // Atur metadata pengguna kustom. Metadata pengguna kustom harus sama dengan informasi yang digunakan saat URL dihasilkan. 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): """ Gunakan URL yang ditandatangani sebelumnya untuk mengunggah file ke OSS. :param signed_url: URL yang ditandatangani sebelumnya. :param file_path: Jalur lengkap file yang akan diunggah. :param headers: Opsional. Header HTTP kustom. :param metadata: Opsional. Metadata kustom. :return: None """ if not headers: headers = {} if not metadata: metadata = {} # Perbarui header dan tambahkan awalan metadata. 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__": // Ganti <signedUrl> dengan URL yang diotorisasi. signed_url = "<signedUrl>" // Tentukan jalur lengkap file lokal. Jika Anda tidak menentukan jalur lokal, file diunggah dari direktori tempat skrip berada secara default. file_path = "C:\\Users\\demo.txt" // Atur header permintaan. Informasi header permintaan harus sama dengan informasi yang digunakan saat URL dihasilkan. headers = { "Content-Type": "text/plain;charset=utf8", "x-oss-storage-class": "Standard" } // Atur metadata pengguna kustom. Metadata pengguna kustom harus sama dengan informasi yang digunakan saat URL dihasilkan. 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 { // Perbarui header dan tambahkan awalan metadata. for (const [key, value] of Object.entries(metadata)) { headers[`x-oss-meta-${key}`] = value; } // Baca aliran file. const fileStream = fs.createReadStream(filePath); // Kirim permintaan PUT. 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}`); } } // Fungsi utama. (async () => { // Ganti <signedUrl> dengan URL yang diotorisasi. const signedUrl = "<signedUrl>"; // Tentukan jalur lengkap file lokal. Jika Anda tidak menentukan jalur lokal, file diunggah dari direktori tempat skrip berada secara default. const filePath = "C:\\Users\\demo.txt"; // Atur header permintaan. Informasi header permintaan harus sama dengan informasi yang digunakan saat URL dihasilkan. const headers = { "Content-Type": "text/plain;charset=utf8", "x-oss-storage-class": "Standard" }; // Atur metadata pengguna kustom. Metadata pengguna kustom harus sama dengan informasi yang digunakan saat URL dihasilkan. const metadata = { "key1": "value1", "key2": "value2" }; await uploadFile(signedUrl, filePath, headers, metadata); })();Browser.js
PentingJika Anda mengalami kesalahan ketidakcocokan tanda tangan 403 saat menggunakan Browser.js untuk mengunggah file, biasanya karena browser secara otomatis menambahkan header permintaan Content-Type, tetapi header ini tidak ditentukan saat URL yang ditandatangani sebelumnya dihasilkan. Hal ini menyebabkan kegagalan verifikasi tanda tangan. Untuk mengatasi masalah ini, Anda harus menentukan header permintaan Content-Type saat menghasilkan URL yang ditandatangani sebelumnya.
<!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> // Ganti ini dengan URL yang ditandatangani sebelumnya yang sebenarnya. 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; // Tentukan jalur lengkap file lokal. Jika Anda tidak menentukan jalur lokal, file diunggah dari jalur proyek program contoh secara default. var filePath = "C:\\Users\\demo.txt"; // Ganti <signedUrl> dengan URL yang diotorisasi. 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; // Jika Anda mengatur parameter header, seperti metadata pengguna dan kelas penyimpanan, saat menghasilkan URL yang ditandatangani sebelumnya, Anda juga harus mengirim parameter ini ke server saat menggunakan URL tersebut untuk mengunggah file. Kesalahan tanda tangan akan dilaporkan jika parameter yang dikirim ke server tidak konsisten dengan parameter yang ditandatangani. // Atur header permintaan. Informasi header permintaan harus sama dengan informasi yang digunakan saat URL dihasilkan. request.Content.Headers.ContentType = new MediaTypeHeaderValue("text/plain") { CharSet = "utf8" }; // Tentukan ContentType. // Atur metadata pengguna kustom. Metadata pengguna kustom harus sama dengan informasi yang digunakan saat URL dihasilkan. request.Content.Headers.Add("x-oss-meta-key1", "value1"); request.Content.Headers.Add("x-oss-meta-key2", "value2"); // Tentukan kelas penyimpanan objek. request.Content.Headers.Add("x-oss-storage-class", "Standard"); // Cetak header permintaan. Console.WriteLine("Request headers:"); foreach (var header in request.Content.Headers) { Console.WriteLine($"{header.Key}: {string.Join(", ", header.Value)}"); } // Kirim permintaan. var response = await httpClient.SendAsync(request); // Proses respons. 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> // Fungsi callback untuk menangani respons HTTP. 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) { // Atur URL. curl_easy_setopt(curl, CURLOPT_URL, signedUrl.c_str()); // Atur metode permintaan menjadi PUT. curl_easy_setopt(curl, CURLOPT_UPLOAD, 1L); // Buka file. FILE* file = fopen(filePath.c_str(), "rb"); if (!file) { std::cerr << "Unable to open file: " << filePath << std::endl; return; } // Atur ukuran file. fseek(file, 0, SEEK_END); long fileSize = ftell(file); rewind(file); // Atur callback baca file. curl_easy_setopt(curl, CURLOPT_READDATA, file); curl_easy_setopt(curl, CURLOPT_INFILESIZE_LARGE, (curl_off_t)fileSize); // Atur header permintaan. 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); // Atur callback penanganan respons. curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback); curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer); // Eksekusi permintaan. res = curl_easy_perform(curl); // Periksa respons. 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; } // Bersihkan. fclose(file); curl_slist_free_all(chunk); curl_easy_cleanup(curl); } curl_global_cleanup(); } int main() { // Ganti <signedUrl> dengan URL yang diotorisasi. std::string signedUrl = "<signedUrl>"; // Tentukan jalur lengkap file lokal. Jika Anda tidak menentukan jalur lokal, file diunggah dari jalur proyek program contoh secara default. std::string filePath = "C:\\Users\\demo.txt"; // Atur header permintaan. Informasi header permintaan harus sama dengan informasi yang digunakan saat URL dihasilkan. std::map<std::string, std::string> headers = { {"Content-Type", "text/plain;charset=utf8"}, {"x-oss-storage-class", "Standard"} }; // Atur metadata pengguna kustom. Metadata pengguna kustom harus sama dengan informasi yang digunakan saat URL dihasilkan. 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); // Ganti <signedUrl> dengan URL yang diotorisasi. String signedUrl = "<signedUrl>"; // Tentukan jalur lengkap file lokal. Jika Anda tidak menentukan jalur lokal, file diunggah dari jalur proyek program contoh secara default. String pathName = "/storage/emulated/0/demo.txt"; // Atur header permintaan. Informasi header permintaan harus sama dengan informasi yang digunakan saat URL dihasilkan. Map<String, String> headers = new HashMap<>(); headers.put("Content-Type", "text/plain;charset=utf8"); headers.put("x-oss-storage-class", "Standard"); // Atur metadata pengguna kustom. Metadata pengguna kustom harus sama dengan informasi yang digunakan saat URL dihasilkan. 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); // Atur header permintaan. for (Entry<String, String> header : headers.entrySet()) { connection.setRequestProperty(header.getKey(), header.getValue()); } // Atur metadata pengguna kustom. for (Entry<String, String> meta : userMetadata.entrySet()) { connection.setRequestProperty("x-oss-meta-" + meta.getKey(), meta.getValue()); } // Baca 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(); // Dapatkan respons. 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(); } } } }
Atur callback unggahan
Saat Anda mengunggah file, Anda dapat menambahkan parameter callback untuk secara otomatis memberi tahu server aplikasi Anda setelah unggahan berhasil. Untuk informasi lebih lanjut tentang prinsip callback, lihat Callback.
Pemilik bucket menghasilkan URL yang ditandatangani sebelumnya untuk permintaan PUT yang mencakup parameter callback unggahan.
Python
import argparse import base64 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 membuat URL yang ditandatangani yang mengizinkan permintaan HTTP PUT. parser = argparse.ArgumentParser(description="presign put object sample") # Tentukan parameter baris perintah, termasuk Wilayah, nama bucket, titik akhir, 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(): # Mengurai parameter baris perintah. args = parser.parse_args() # Dapatkan kredensial akses dari variabel lingkungan untuk autentikasi. credentials_provider = oss.credentials.EnvironmentVariableCredentialsProvider() # Gunakan konfigurasi default untuk membuat objek cfg dan tentukan penyedia kredensial. cfg = oss.config.load_default() cfg.credentials_provider = credentials_provider # Atur atribut Wilayah dari objek cfg ke Wilayah yang disediakan di baris perintah. cfg.region = args.region # Jika titik akhir kustom disediakan, perbarui atribut titik akhir dari objek cfg dengan titik akhir yang disediakan. if args.endpoint is not None: cfg.endpoint = args.endpoint # Gunakan konfigurasi sebelumnya untuk menginisialisasi instans OSSClient. client = oss.Client(cfg) # Tentukan URL callback kustom. call_back_url = "http://www.example.com/callback" # Buat parameter callback: tentukan URL callback dan badan permintaan, dan enkode parameter dalam Base64. callback=base64.b64encode(str('{\"callbackUrl\":\"' + call_back_url + '\",\"callbackBody\":\"bucket=${bucket}&object=${object}&my_var_1=${x:var1}&my_var_2=${x:var2}\"}').encode()).decode() # Tentukan variabel callback kustom dan enkode ke Base64. callback_var=base64.b64encode('{\"x:var1\":\"value1\",\"x:var2\":\"value2\"}'.encode()).decode() # Kirim permintaan untuk memulai permintaan PUT dan buat URL yang ditandatangani untuk objek yang ditentukan. pre_result = client.presign(oss.PutObjectRequest( bucket=args.bucket, # Nama bucket. key=args.key, # Nama objek. callback=callback, callback_var=callback_var, ),expires=timedelta(seconds=3600)) # Tentukan periode validitas permintaan. Dalam contoh ini, periode validitas diatur ke 3.600 detik. # Tampilkan metode, waktu kedaluwarsa, dan URL yang ditandatangani yang ditentukan dalam permintaan untuk memeriksa validitas URL yang ditandatangani. print(f'method: {pre_result.method},' f' expiration: {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'signed headers key: {key}, signed headers value: {value}') # Panggil fungsi utama untuk memulai logika pemrosesan saat skrip dijalankan secara langsung. if __name__ == "__main__": main() # Tentukan titik masuk skrip. Alur kontrol dimulai di sini.Go
package main import ( "context" "encoding/base64" "encoding/json" "flag" "log" "time" "github.com/aliyun/alibabacloud-oss-go-sdk-v2/oss" "github.com/aliyun/alibabacloud-oss-go-sdk-v2/oss/credentials" ) // Definisikan variabel global. var ( region string // Wilayah tempat bucket berada. bucketName string // Nama bucket. objectName string // Nama objek. ) // Tentukan fungsi init yang digunakan untuk menginisialisasi parameter baris perintah. func init() { flag.StringVar(®ion, "region", "", "The region in which the bucket is located.") flag.StringVar(&bucketName, "bucket", "", "The name of the bucket.") flag.StringVar(&objectName, "object", "", "The name of the object.") } func main() { // Uraikan parameter baris perintah. flag.Parse() // Periksa apakah nama bucket ditentukan. if len(bucketName) == 0 { flag.PrintDefaults() log.Fatalf("invalid parameters, bucket name required") } // Periksa apakah wilayah ditentukan. if len(region) == 0 { flag.PrintDefaults() log.Fatalf("invalid parameters, region required") } // Periksa apakah nama objek ditentukan. if len(objectName) == 0 { flag.PrintDefaults() log.Fatalf("invalid parameters, object name required") } // Muat konfigurasi default dan tentukan penyedia kredensial serta wilayah. cfg := oss.LoadDefaultConfig(). WithCredentialsProvider(credentials.NewEnvironmentVariableCredentialsProvider()). WithRegion(region) // Buat klien OSS. client := oss.NewClient(cfg) // Tentukan parameter callback. callbackMap := map[string]string{ "callbackUrl": "http://example.com:23450", // Tentukan URL server callback. Contoh: https://example.com:23450. "callbackBody": "bucket=${bucket}&object=${object}&size=${size}&my_var_1=${x:my_var1}&my_var_2=${x:my_var2}", // Tentukan isi permintaan callback. "callbackBodyType": "application/x-www-form-urlencoded", // Tentukan tipe isi permintaan callback. } // Konversi konfigurasi parameter callback ke string JSON dan enkode string tersebut dalam Base64 untuk meneruskan konfigurasi callback. callbackStr, err := json.Marshal(callbackMap) if err != nil { log.Fatalf("failed to marshal callback map: %v", err) } callbackBase64 := base64.StdEncoding.EncodeToString(callbackStr) callbackVarMap := map[string]string{} callbackVarMap["x:my_var1"] = "thi is var 1" callbackVarMap["x:my_var2"] = "thi is var 2" callbackVarStr, err := json.Marshal(callbackVarMap) if err != nil { log.Fatalf("failed to marshal callback var: %v", err) } callbackVarBase64 := base64.StdEncoding.EncodeToString(callbackVarStr) // Hasilkan URL yang ditandatangani sebelumnya untuk permintaan PutObject. result, err := client.Presign(context.TODO(), &oss.PutObjectRequest{ Bucket: oss.Ptr(bucketName), Key: oss.Ptr(objectName), Callback: oss.Ptr(callbackBase64), // Atur parameter callback, yang merupakan string JSON yang dienkode Base64 dalam kasus ini. CallbackVar: oss.Ptr(callbackVarBase64), // Tentukan parameter kustom untuk permintaan callback, yang merupakan string JSON yang dienkode Base64 dalam contoh ini. }, oss.PresignExpires(10*time.Minute), ) if err != nil { log.Fatalf("failed to put object presign %v", err) } log.Printf("request method:%v\n", result.Method) log.Printf("request expiration:%v\n", result.Expiration) log.Printf("request url:%v\n", result.URL) if len(result.SignedHeaders) > 0 { // Jika Anda menentukan header permintaan saat menghasilkan URL yang ditandatangani sebelumnya yang memungkinkan permintaan HTTP PUT, pastikan header permintaan tersebut disertakan dalam permintaan PUT yang diprakarsai menggunakan URL tersebut. log.Printf("signed headers:\n") for k, v := range result.SignedHeaders { log.Printf("%v: %v\n", k, v) } } }Java
import com.aliyun.oss.*; import com.aliyun.oss.common.auth.CredentialsProviderFactory; import com.aliyun.oss.common.auth.EnvironmentVariableCredentialsProvider; import com.aliyun.oss.common.comm.SignVersion; import com.aliyun.oss.internal.OSSHeaders; import com.aliyun.oss.model.GeneratePresignedUrlRequest; import java.net.URL; import java.text.SimpleDateFormat; import java.util.*; public class OssPresignExample { public static void main(String[] args) throws Throwable { // Contoh ini menggunakan titik akhir publik wilayah China (Hangzhou). Tentukan titik akhir yang sebenarnya. String endpoint = "https://oss-cn-hangzhou.aliyuncs.com"; // Dapatkan kredensial akses dari variabel lingkungan. Sebelum menjalankan kode contoh, pastikan variabel lingkungan OSS_ACCESS_KEY_ID dan OSS_ACCESS_KEY_SECRET telah dikonfigurasi. EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider(); // Tentukan nama bucket, misalnya examplebucket. String bucketName = "examplebucket"; // Tentukan jalur lengkap objek, misalnya exampleobject.txt. Jalur lengkap objek tidak boleh mengandung nama bucket. String objectName = "exampleobject.txt"; // Tentukan wilayah tempat bucket berada. Misalnya, jika bucket berada di wilayah China (Hangzhou), atur wilayah menjadi cn-hangzhou. String region = "cn-hangzhou"; // Buat instance OSSClient. // Saat instance OSSClient tidak lagi digunakan, panggil metode shutdown untuk melepaskan sumber daya. ClientBuilderConfiguration clientBuilderConfiguration = new ClientBuilderConfiguration(); clientBuilderConfiguration.setSignatureVersion(SignVersion.V4); OSS ossClient = OSSClientBuilder.create() .endpoint(endpoint) .credentialsProvider(credentialsProvider) .clientConfiguration(clientBuilderConfiguration) .region(region) .build(); URL signedUrl = null; try { // Bangun parameter callback. String callbackUrl = "http://www.example.com/callback"; String callbackBody = "{\"callbackUrl\":\"" + callbackUrl + "\",\"callbackBody\":\"bucket=${bucket}&object=${object}&my_var_1=${x:var1}&my_var_2=${x:var2}\"}"; String callbackBase64 = Base64.getEncoder().encodeToString(callbackBody.getBytes()); String callbackVarJson = "{\"x:var1\":\"value1\",\"x:var2\":\"value2\"}"; String callbackVarBase64 = Base64.getEncoder().encodeToString(callbackVarJson.getBytes()); // Atur header permintaan. Map<String, String> headers = new HashMap<String, String>(); // Tentukan CALLBACK. headers.put(OSSHeaders.OSS_HEADER_CALLBACK, callbackBase64); // Tentukan CALLBACK-VAR. headers.put(OSSHeaders.OSS_HEADER_CALLBACK_VAR, callbackVarBase64); // Atur waktu kedaluwarsa (3600 detik kemudian). Date expiration = new Date(new Date().getTime() + 3600 * 1000); // Format waktu kedaluwarsa. SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"); dateFormat.setTimeZone(TimeZone.getTimeZone("UTC")); String expirationStr = dateFormat.format(expiration); // Bangun permintaan. GeneratePresignedUrlRequest request = new GeneratePresignedUrlRequest(bucketName, objectName); request.setMethod(HttpMethod.PUT); request.setExpiration(expiration); // Tambahkan header permintaan ke permintaan. request.setHeaders(headers); // Cetak parameter callback dan callback-var. System.out.println("callback:"+callbackBase64); System.out.println("callback-var:"+callbackVarBase64); // Hasilkan URL yang ditandatangani sebelumnya. URL url = ossClient.generatePresignedUrl(request); // Cetak hasil. System.out.println("method: PUT,"); System.out.println(" expiration: " + expirationStr + ","); System.out.println(" url: " + url); } catch (OSSException oe) { System.out.println("Caught an OSSException, which means your request made it to OSS, " + "but was rejected with an error response for some reason."); System.out.println("Error Message:" + oe.getErrorMessage()); System.out.println("Error Code:" + oe.getErrorCode()); System.out.println("Request ID:" + oe.getRequestId()); System.out.println("Host ID:" + oe.getHostId()); } catch (ClientException ce) { System.out.println("Caught an ClientException, which means the client encountered " + "a serious internal problem while trying to communicate with OSS, " + "such as not being able to access the network."); System.out.println("Error Message:" + ce.getMessage()); } } }PHP
<?php // Sertakan file autoload untuk memuat dependensi. require_once __DIR__ . '/../vendor/autoload.php'; use AlibabaCloud\Oss\V2 as Oss; // Definisikan dan jelaskan opsi baris perintah. $optsdesc = [ "region" => ['help' => 'The region in which the bucket is located.', 'required' => True], // (Wajib) Tentukan wilayah tempat bucket berada. "endpoint" => ['help' => 'The domain names that other services can use to access OSS.', 'required' => False], // (Opsional) Tentukan titik akhir untuk mengakses OSS. "bucket" => ['help' => 'The name of the bucket', 'required' => True], // (Wajib) Tentukan nama bucket. "key" => ['help' => 'The name of the object', 'required' => True], // (Wajib) Tentukan nama objek. ]; // Konversi deskripsi ke daftar opsi panjang yang diperlukan oleh getopt. // Tambahkan titik dua (:) di akhir setiap opsi untuk menunjukkan bahwa nilai diperlukan. $longopts = \array_map(function ($key) { return "$key:"; }, array_keys($optsdesc)); // Uraikan opsi baris perintah. $options = getopt("", $longopts); // Periksa apakah opsi wajib telah dikonfigurasi. foreach ($optsdesc as $key => $value) { if ($value['required'] === True && empty($options[$key])) { $help = $value['help']; // Dapatkan informasi bantuan. echo "Error: the following arguments are required: --$key, $help" . PHP_EOL; exit(1); // Keluar dari program jika opsi wajib hilang. } } // Tetapkan nilai yang diuraikan dari opsi baris perintah ke variabel yang sesuai. $region = $options["region"]; // Wilayah tempat bucket berada. $bucket = $options["bucket"]; // Nama bucket. $key = $options["key"]; // Nama objek. // Muat kredensial akses dari variabel lingkungan. // Gunakan EnvironmentVariableCredentialsProvider untuk mengambil ID AccessKey dan rahasia AccessKey dari variabel lingkungan. $credentialsProvider = new Oss\Credentials\EnvironmentVariableCredentialsProvider(); // Gunakan konfigurasi default SDK. $cfg = Oss\Config::loadDefault(); $cfg->setCredentialsProvider($credentialsProvider); // Tentukan penyedia kredensial. $cfg->setRegion($region); // Tentukan wilayah tempat bucket berada. if (isset($options["endpoint"])) { $cfg->setEndpoint($options["endpoint"]); // Tentukan titik akhir jika disediakan. } // Buat instance OSSClient. $client = new Oss\Client($cfg); // Sertakan header x-oss-callback dan x-oss-callback-var. // Tentukan URL callback. $call_back_url = "http://www.example.com/callback"; // Bangun parameter callback: Tentukan URL callback dan isi permintaan, keduanya harus dienkode Base64. // Ganti ${x:var1} dan ${x:var2} dengan placeholder {var1} dan {var2}. $callback_body_template = "bucket={bucket}&object={object}&my_var_1={var1}&my_var_2={var2}"; $callback_body_replaced = str_replace( ['{bucket}', '{object}', '{var1}', '{var2}'], [$bucket, $key, 'value1', 'value2'], $callback_body_template ); $callback = base64_encode(json_encode([ "callbackUrl" => $call_back_url, "callbackBody" => $callback_body_replaced ])); // Definisikan dan enkode Base64 variabel callback kustom. $callback_var = base64_encode(json_encode([ "x:var1" => "value1", "x:var2" => "value2" ])); // Buat objek PutObjectRequest untuk mengunggah data. // Perhatikan bahwa Content-Type, metadata, dan header disertakan untuk perhitungan tanda tangan. $request = new Oss\Models\PutObjectRequest( bucket: $bucket, key: $key, callback:$callback, callbackVar:$callback_var, ); // Panggil metode presign untuk menghasilkan permintaan yang ditandatangani sebelumnya. $result = $client->presign($request); // Tampilkan URL yang ditandatangani sebelumnya, yang dapat digunakan untuk mengunggah objek yang ditentukan. print( 'put object presign result:' . var_export($result, true) . PHP_EOL . 'put object url:' . $result->url . PHP_EOL );Pihak ketiga menggunakan URL yang ditandatangani sebelumnya untuk permintaan PUT guna mengunggah file.
curl
curl -X PUT \ -H "x-oss-callback: eyJjYWxsYmFja1VybCI6Imh0dHA6Ly93d3cuZXhhbXBsZS5jb20vY2FsbGJhY2siLCJjYWxsYmFja0JvZHkiOiJidWNrZXQ9JHtidWNrZXR9Jm9iamVjdD0ke29iamVjdH0mbXlfdmFyXzE9JHt4OnZhcjF9Jm15X3Zhcl8yPSR7eDp2YXIyfSJ9" \ -H "x-oss-callback-var: eyJ4OnZhcjEiOiJ2YWx1ZTEiLCJ4OnZhcjIiOiJ2YWx1ZTIifQ==" \ -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******************************************************"Python
import requests def upload_file(signed_url, file_path, headers=None): """ Gunakan URL yang ditandatangani sebelumnya untuk mengunggah objek ke OSS. :param signed_url: URL yang ditandatangani sebelumnya. :param file_path: Jalur lengkap file lokal yang akan diunggah. :param headers: Header permintaan. Parameter ini opsional. :return: None """ if not headers: headers = {} try: with open(file_path, 'rb') as file: response = requests.put(signed_url, data=file, headers=headers) print(f"Status code: {response.status_code}") if response.status_code == 200: print("The object is uploaded by using the library.") else: print("Upload failed.") print(response.text) except Exception as e: print(f"An error occurred: {e}") if __name__ == "__main__": // Ganti <signedUrl> dengan URL yang ditandatangani sebelumnya. signed_url = "<signedUrl>" // Tentukan jalur lengkap file lokal. Secara default, jika Anda tidak menentukan jalur lengkap file lokal, file lokal diunggah dari direktori tempat skrip disimpan. file_path = "C:\\Users\\demo.txt" headers = { "x-oss-callback": "eyJjYWxsYmFja1VybCI6Imh0dHA6Ly93d3cuZXhhbXBsZS5jb20vY2FsbGJhY2siLCJjYWxsYmFja0JvZHkiOiJidWNrZXQ9JHtidWNrZXR9Jm9iamVjdD0ke29iamVjdH0mbXlfdmFyXzE9JHt4OnZhcjF9Jm15X3Zhcl8yPSR7eDp2YXIyfSJ9", "x-oss-callback-var": "eyJ4OnZhcjEiOiJ2YWx1ZTEiLCJ4OnZhcjIiOiJ2YWx1ZTIifQ==", } upload_file(signed_url, file_path, headers)Go
package main import ( "bytes" "fmt" "io" "net/http" "os" ) func uploadFile(signedUrl string, filePath string, headers map[string]string) error { // Buka file. file, err := os.Open(filePath) if err != nil { return err } defer file.Close() // Baca konten. fileBytes, err := io.ReadAll(file) if err != nil { return err } // Buat permintaan. req, err := http.NewRequest("PUT", signedUrl, bytes.NewBuffer(fileBytes)) if err != nil { return err } // Tentukan header permintaan. for key, value := range headers { req.Header.Add(key, value) } // Kirim permintaan. client := &http.Client{} resp, err := client.Do(req) if err != nil { return err } defer resp.Body.Close() // Proses respons. fmt.Printf("Status code: %d\n", resp.StatusCode) if resp.StatusCode == 200 { fmt.Println("The object is uploaded by using the library.") } else { fmt.Println("Upload failed.") } body, _ := io.ReadAll(resp.Body) fmt.Println(string(body)) return nil } func main() { // Ganti <signedUrl> dengan URL yang ditandatangani sebelumnya. signedUrl := "<signedUrl>" // Tentukan jalur lengkap file lokal. Jika jalur file lokal tidak ditentukan, file lokal diunggah dari jalur proyek tempat program contoh berada. filePath := "C:\\Users\\demo.txt" // Tentukan header permintaan. Pastikan nilai header permintaan sama dengan yang ditentukan saat URL yang ditandatangani sebelumnya dihasilkan. headers := map[string]string{ "x-oss-callback": "eyJjYWxsYmFja1VybCI6Imh0dHA6Ly93d3cuZXhhbXBsZS5jb20vY2FsbGJhY2siLCJjYWxsYmFja0JvZHkiOiJidWNrZXQ9JHtidWNrZXR9Jm9iamVjdD0ke29iamVjdH0mbXlfdmFyXzE9JHt4OnZhcjF9Jm15X3Zhcl8yPSR7eDp2YXIyfSJ9", "x-oss-callback-var": "eyJ4OnZhcjEiOiJ2YWx1ZTEiLCJ4OnZhcjIiOiJ2YWx1ZTIifQ==", } err := uploadFile(signedUrl, filePath, headers) if err != nil { fmt.Printf("An error occurred: %v\n", err) } }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 yang ditandatangani sebelumnya. URL signedUrl = new URL("<signedUrl>"); // Tentukan jalur lengkap file lokal. Jika jalur file lokal tidak ditentukan, file lokal diunggah dari jalur proyek tempat program contoh berada. String pathName = "C:\\Users\\demo.txt"; // Tentukan header permintaan, termasuk x-oss-callback dan x-oss-callback-var. Map<String, String> headers = new HashMap<String, String>(); headers.put("x-oss-callback", "eyJjYWxsYmFja1VybCI6Imh0dHA6Ly93d3cuZXhhbXBsZS5jb20vY2FsbGJhY2siLCJjYWxsYmFja0JvZHkiOiJidWNrZXQ9JHtidWNrZXR9Jm9iamVjdD0ke29iamVjdH0mbXlfdmFyXzE9JHt4OnZhcjF9Jm15X3Zhcl8yPSR7eDp2YXIyfSJ9"); headers.put("x-oss-callback-var", "eyJ4OnZhcjEiOiJ2YWx1ZTEiLCJ4OnZhcjIiOiJ2YWx1ZTIifQ=="); try { HttpPut put = new HttpPut(signedUrl.toString()); System.out.println(put); HttpEntity entity = new FileEntity(new File(pathName)); put.setEntity(entity); // Jika Anda mengonfigurasi header saat URL yang ditandatangani sebelumnya dihasilkan, header ini harus dikirim ke server saat URL tersebut digunakan untuk mengunggah file. Jika header yang dikirim ke server untuk perhitungan tanda tangan berbeda dengan header yang ditentukan saat URL yang ditandatangani sebelumnya dihasilkan, kesalahan tanda tangan akan dilaporkan. for(Map.Entry header: headers.entrySet()){ put.addHeader(header.getKey().toString(),header.getValue().toString()); } httpClient = HttpClients.createDefault(); response = httpClient.execute(put); System.out.println("Status code: "+response.getStatusLine().getStatusCode()); if(response.getStatusLine().getStatusCode() == 200){ System.out.println("The object is uploaded by using the library."); } System.out.println(response.toString()); } catch (Exception e){ e.printStackTrace(); } finally { response.close(); httpClient.close(); } } }PHP
<?php function uploadFile($signedUrl, $filePath, $headers = []) { // Periksa apakah file ada. if (!file_exists($filePath)) { echo "The file does not exist: $filePath\n"; return; } // Inisialisasi sesi cURL. $ch = curl_init(); // Atur opsi cURL. curl_setopt($ch, CURLOPT_URL, $signedUrl); curl_setopt($ch, CURLOPT_PUT, true); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_INFILE, fopen($filePath, 'rb')); curl_setopt($ch, CURLOPT_INFILESIZE, filesize($filePath)); curl_setopt($ch, CURLOPT_HTTPHEADER, array_map(function($key, $value) { return "$key: $value"; }, array_keys($headers), $headers)); // Lakukan permintaan cURL. $response = curl_exec($ch); // Kueri kode status HTTP. $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); // Tutup sesi cURL. curl_close($ch); // Keluarkan hasil echo "Status code: $httpCode\n"; if ($httpCode == 200) { echo "The object is uploaded by using the library.\n"; } else { echo "Upload failed.\n"; } echo $response . "\n"; } // Ganti <signedUrl> dengan URL yang ditandatangani sebelumnya. $signedUrl = "<signedUrl>"; // Tentukan jalur lengkap file lokal. Secara default, jika Anda tidak menentukan jalur lengkap file lokal, file lokal diunggah dari direktori tempat skrip disimpan. $filePath = "C:\\Users\\demo.txt"; $headers = [ "x-oss-callback" => "eyJjYWxsYmFja1VybCI6Imh0dHA6Ly93d3cuZXhhbXBsZS5jb20vY2FsbGJhY2siLCJjYWxsYmFja0JvZHkiOiJidWNrZXQ9JHtidWNrZXR9Jm9iamVjdD0ke29iamVjdH0mbXlfdmFyXzE9JHt4OnZhcjF9Jm15X3Zhcl8yPSR7eDp2YXIyfSJ9", "x-oss-callback-var" => "eyJ4OnZhcjEiOiJ2YWx1ZTEiLCJ4OnZhcjIiOiJ2YWx1ZTIifQ==", ]; uploadFile($signedUrl, $filePath, $headers); ?>
Pelajari lebih lanjut
Apa itu URL yang ditandatangani sebelumnya
URL yang ditandatangani sebelumnya adalah tautan aman yang memberikan akses sementara ke file OSS tertentu menggunakan tanda tangan terenkripsi dan verifikasi periode validitas. Saat URL yang ditandatangani sebelumnya dihasilkan, tanda tangan terenkripsi dihitung secara lokal berdasarkan pasangan AccessKey, jalur sumber daya, waktu kedaluwarsa, dan parameter lainnya. Parameter tanda tangan kemudian ditambahkan ke URL untuk membentuk URL yang ditandatangani sebelumnya lengkap. Format tipikalnya adalah: https://BucketName.Endpoint/Object?signature_parameters.
Saat pihak ketiga mengakses URL ini, OSS memverifikasi parameter tanda tangan. Jika parameter telah dimanipulasi atau URL telah kedaluwarsa, akses ditolak.
Berikut adalah contoh URL yang ditandatangani sebelumnya.
https://examplebucket.oss-cn-hangzhou.aliyuncs.com/exampleobject.txt?x-oss-process=image%2Fresize%2Cp_10&x-oss-date=20241115T095058Z&x-oss-expires=3600&x-oss-signature-version=OSS4-HMAC-SHA256&x-oss-credential=LTAI****************%2F20241115%2Fcn-hangzhou%2Foss%2Faliyun_v4_request&x-oss-signature=6e7a********************************Dengan cara ini, pemilik bucket dapat memberi otorisasi akses pihak ketiga ke file secara aman tanpa mengekspos pasangan AccessKey.
Skenario
Berbagi file jangka pendek: Pihak ketiga meminta untuk mengunggah atau mengunduh file tertentu. Backend menghasilkan URL yang ditandatangani sebelumnya dengan periode validitas dan mengembalikannya ke frontend. Pihak ketiga dapat menggunakan URL ini untuk mengunggah atau mengunduh file dalam periode validitas, yang menjamin keamanan data.
Akses fleksibel: Pemilik bucket dapat membagikan URL yang ditandatangani sebelumnya melalui email atau obrolan. Pihak ketiga kemudian dapat menempelkan URL tersebut ke bilah alamat browser untuk mengunduh file.