全部产品
Search
文档中心

Object Storage Service:Unggah formulir (PHP SDK V2)

更新时间:Nov 09, 2025

Unggah formulir memungkinkan Anda mengunggah objek langsung ke Object Storage Service (OSS) menggunakan formulir HTML standar dari aplikasi web. Topik ini menjelaskan cara menghasilkan informasi seperti tanda tangan dan kebijakan unggah menggunakan OSS SDK untuk PHP 2.0, serta cara menggunakan metode HTTP POST untuk mengunggah objek ke OSS.

Catatan

  • Kode contoh dalam topik ini menggunakan ID wilayah cn-hangzhou dari wilayah China (Hangzhou). Secara default, titik akhir publik digunakan untuk mengakses sumber daya di bucket. Jika Anda ingin mengakses sumber daya di bucket dari layanan Alibaba Cloud lainnya di wilayah yang sama, gunakan titik akhir internal. Untuk informasi lebih lanjut tentang wilayah dan titik akhir yang didukung, lihat Wilayah dan titik akhir OSS.

  • Ukuran objek yang ingin Anda unggah menggunakan form upload tidak boleh melebihi 5 GB.

  • Dalam topik ini, kredensial akses diperoleh dari variabel lingkungan. Untuk instruksi lebih lanjut, lihat Konfigurasi kredensial akses di PHP.

Kode contoh

Berikut adalah kode contoh yang menunjukkan cara melakukan form upload. Proses lengkap form upload terdiri dari langkah-langkah berikut:

  1. Buat Kebijakan Post: Tentukan periode validitas dan kondisi permintaan unggah, termasuk nama bucket, versi tanda tangan, kredensial, tanggal permintaan, dan rentang panjang badan permintaan.

  2. Proses kebijakan unggah: Ubah kebijakan unggah menjadi string JSON dan enkode Base64 string tersebut.

  3. Hasilkan kunci penandatanganan: Gunakan algoritma HMAC-SHA256 untuk menghasilkan kunci penandatanganan termasuk tanggal, wilayah, layanan, dan jenis permintaan.

  4. Hitung tanda tangan: Gunakan kunci yang dihasilkan untuk menandatangani string kebijakan yang di-enkode Base64 dan ubah tanda tangan menjadi string heksadesimal.

  5. Buat badan permintaan: Buat pembuat formulir multipart, tentukan kunci objek, kebijakan, versi tanda tangan, kredensial, tanggal permintaan, dan tanda tangan dalam formulir, serta tulis data yang ingin Anda unggah ke formulir.

  6. Buat dan jalankan permintaan: Buat permintaan HTTP POST dan tentukan header permintaan. Kirim permintaan dan periksa kode status respons untuk memastikan bahwa permintaan berhasil.

<?php

// Sertakan file autoload untuk memuat dependensi.
require_once __DIR__ . '/../vendor/autoload.php';

use AlibabaCloud\Oss\V2 as Oss;

// Definisikan dan jelaskan parameter baris perintah.
$optsdesc = [
    "region" => ['help' => 'Wilayah tempat bucket berada.', 'required' => True], // (Diperlukan) Wilayah tempat bucket berada.
    "bucket" => ['help' => 'Nama bucket', 'required' => True], // (Diperlukan) Nama bucket.
    "key" => ['help' => 'Nama objek', 'required' => True], // (Diperlukan) Nama objek.
];

// Konversikan deskripsi menjadi daftar opsi panjang yang diperlukan oleh getopt.
// Tambahkan titik dua (:) di akhir setiap parameter untuk menunjukkan bahwa nilai diperlukan.
$longopts = \array_map(function ($key) {
    return "$key:";
}, array_keys($optsdesc));

// Parsing parameter baris perintah.
$options = getopt("", $longopts);

// Periksa apakah parameter yang diperlukan telah dikonfigurasi.
foreach ($optsdesc as $key => $value) {
    if ($value['required'] === True && empty($options[$key])) {
        $help = $value['help']; // Dapatkan informasi bantuan untuk parameter.
        echo "Error: argumen berikut diperlukan: --$key, $help" . PHP_EOL;
        exit(1); // Keluar dari program jika parameter yang diperlukan hilang
    }
}

// Ekstrak nilai dari parameter yang diparsing
$region = $options["region"]; // Wilayah tempat bucket berada
$bucket = $options["bucket"]; // Nama bucket
$key = $options["key"];       // Nama objek
$product = 'oss';             // Tetap sebagai layanan OSS

// Muat informasi kredensial dari variabel lingkungan
// Gunakan EnvironmentVariableCredentialsProvider untuk membaca Access Key ID dan Access Key Secret dari variabel lingkungan
$credentialsProvider = new Oss\Credentials\EnvironmentVariableCredentialsProvider();
$cred = $credentialsProvider->getCredentials();

// Konten data yang akan diunggah
$data = 'hi oss'; // Data contoh, dapat diganti dengan konten lain dalam penggunaan sebenarnya

// Dapatkan waktu UTC saat ini dan formatnya
$utcTime = new DateTime('now', new DateTimeZone('UTC'));
$date = $utcTime->format('Ymd'); // Tanggal saat ini, digunakan untuk perhitungan tanda tangan
$expiration = clone $utcTime;
$expiration->add(new DateInterval('PT1H')); // Setel waktu kedaluwarsa menjadi 1 jam kemudian

// Bangun dokumen Policy
$policyMap = [
    "expiration" => $expiration->format('Y-m-d\TH:i:s.000\Z'), // Waktu kedaluwarsa Policy
    "conditions" => [
        ["bucket" => $bucket], // Tentukan nama bucket
        ["x-oss-signature-version" => "OSS4-HMAC-SHA256"], // Versi tanda tangan
        ["x-oss-credential" => sprintf("%s/%s/%s/%s/aliyun_v4_request",
            $cred->getAccessKeyId(), $date, $region, $product)], // Informasi kredensial
        ["x-oss-date" => $utcTime->format('Ymd\THis\Z')], // Timestamp saat ini
        // Kondisi lainnya
        ["content-length-range", 1, 1024], // Batasan rentang ukuran file
        // ["eq", "$success_action_status", "201"], // Opsional: tentukan kode status sukses
        // ["starts-with", "$key", "user/eric/"], // Opsional: tentukan awalan kunci objek
        // ["in", "$content-type", ["image/jpg", "image/png"]], // Opsional: tentukan tipe konten yang diizinkan
        // ["not-in", "$cache-control", ["no-cache"]], // Opsional: kecualikan header kontrol cache tertentu
    ],
];

// Enkode dokumen Policy sebagai string JSON
$jsonOptions = JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE; // Cegah pelarian garis miring dan karakter Unicode
$policy = json_encode($policyMap, $jsonOptions);
if (json_last_error() !== JSON_ERROR_NONE) {
    error_log("json_encode gagal, err: " . json_last_error_msg()); // Periksa apakah pengkodean JSON gagal
    exit(1);
}

// Hitung informasi yang diperlukan untuk tanda tangan
$stringToSign = base64_encode($policy); // Enkode Base64 Policy
$signingKey = "aliyun_v4" . $cred->getAccessKeySecret(); // Bangun kunci penandatanganan
$h1Key = hmacSign($signingKey, $date); // Langkah 1: Tandatangani tanggal
$h2Key = hmacSign($h1Key, $region);   // Langkah 2: Tandatangani wilayah
$h3Key = hmacSign($h2Key, $product);  // Langkah 3: Tandatangani produk
$h4Key = hmacSign($h3Key, "aliyun_v4_request"); // Langkah 4: Tandatangani permintaan

// Hitung tanda tangan akhir
$signature = hash_hmac('sha256', $stringToSign, $h4Key);

// Bangun data formulir untuk permintaan POST
$bodyWriter = new CURLFileUpload(); // Buat instance pembuat formulir

// Tambahkan bidang ke formulir
$bodyWriter->addField('key', $key); // Nama objek
$bodyWriter->addField('policy', $stringToSign); // Policy yang di-enkode Base64
$bodyWriter->addField('x-oss-signature-version', 'OSS4-HMAC-SHA256'); // Versi tanda tangan
$bodyWriter->addField('x-oss-credential', sprintf("%s/%s/%s/%s/aliyun_v4_request",
    $cred->getAccessKeyId(), $date, $region, $product)); // Informasi kredensial
$bodyWriter->addField('x-oss-date', $utcTime->format('Ymd\THis\Z')); // Timestamp
$bodyWriter->addField('x-oss-signature', $signature); // Tanda tangan akhir

// Tambahkan konten file ke formulir
$bodyWriter->addFileFromString('file', $data); // Unggah konten file
$postData = $bodyWriter->getFormData(); // Dapatkan data formulir lengkap

// Kirim permintaan POST
$client = new \GuzzleHttp\Client(); // Buat klien HTTP
$response = $client->post(
    sprintf("http://%s.oss-%s.aliyuncs.com/", $bucket, $region), // URL unggah OSS
    [
        'headers' => [
            'content-type' => $bodyWriter->getContentType(), // Setel Content-Type
        ],
        'body' => $postData // Setel badan permintaan
    ]
);

// Periksa kode status respons
if ($response->getStatusCode() < 200 || $response->getStatusCode() >= 300) {
    echo "Post Object Gagal, kode status:" . $response->getStatusCode() . ", alasan: " . $response->getReasonPhrase() . PHP_EOL;
    exit(1); // Keluar dari program jika kode status tidak dalam rentang 2xx
}

// Cetak hasil unggah
echo "post object selesai, kode status:" . $response->getStatusCode() . ", request id:" . $response->getHeaderLine('x-oss-request-id') . PHP_EOL;

/**
 * Fungsi tanda tangan HMAC
 * @param string $key Kunci penandatanganan
 * @param string $data Data yang akan ditandatangani
 * @return string Mengembalikan hasil tanda tangan
 */
function hmacSign($key, $data)
{
    return hash_hmac('sha256', $data, $key, true); // Hasilkan tanda tangan HMAC menggunakan algoritma SHA256
}

/**
 * Kelas pembuat formulir untuk menghasilkan format permintaan multipart/form-data
 */
class CURLFileUpload
{
    private $fields = []; // Simpan bidang reguler
    private $files = [];  // Simpan bidang file
    private $boundary;    // Pemisah

    public function __construct()
    {
        $this->boundary = uniqid(); // Hasilkan pemisah unik
    }

    /**
     * Tambahkan bidang reguler
     * @param string $name Nama bidang
     * @param string $value Nilai bidang
     */
    public function addField($name, $value)
    {
        $this->fields[$name] = $value;
    }

    /**
     * Tambahkan bidang file
     * @param string $name Nama bidang
     * @param string $content Konten file
     */
    public function addFileFromString($name, $content)
    {
        $this->files[$name] = [
            'content' => $content,
            'filename' => $name,
            'type' => 'application/octet-stream' // Tipe MIME default
        ];
    }

    /**
     * Dapatkan data formulir lengkap
     * @return string Mengembalikan badan permintaan dalam format multipart/form-data
     */
    public function getFormData()
    {
        $data = '';
        foreach ($this->fields as $name => $value) {
            $data .= "--{$this->boundary}\r\n";
            $data .= "Content-Disposition: form-data; name=\"$name\"\r\n\r\n";
            $data .= $value . "\r\n";
        }
        foreach ($this->files as $name => $file) {
            $data .= "--{$this->boundary}\r\n";
            $data .= "Content-Disposition: form-data; name=\"$name\"; filename=\"{$file['filename']}\"\r\n";
            $data .= "Content-Type: {$file['type']}\r\n\r\n";
            $data .= $file['content'] . "\r\n";
        }
        $data .= "--{$this->boundary}--\r\n";
        return $data;
    }

    /**
     * Dapatkan header Content-Type
     * @return string Mengembalikan nilai Content-Type
     */
    public function getContentType()
    {
        return "multipart/form-data; boundary={$this->boundary}";
    }
}

Referensi