Todos los productos
Search
Centro de documentos

Object Storage Service:Carga mediante formulario (SDK de PHP V2)

Última actualización: Sep 03, 2026

La carga mediante formulario permite cargar objetos directamente a Object Storage Service (OSS) mediante formularios HTML estándar desde aplicaciones web. Utilice el SDK de OSS para PHP V2 para generar una firma y una directiva de carga; después, use el método HTTP POST para cargar un objeto en OSS.

Notas

  • El código de ejemplo de este tema usa el ID de región cn-hangzhou, correspondiente a la región China (Hangzhou). De forma predeterminada, se usa un endpoint público para acceder a los recursos de un bucket. Si desea acceder a los recursos del bucket desde otros servicios de Alibaba Cloud en la misma región, utilice un endpoint interno. Para obtener más información sobre las regiones y endpoints compatibles, consulte OSS regions and endpoints.

  • El tamaño máximo de un objeto cargado mediante este método es de 5 GB.

  • En este tema, las credenciales de acceso se obtienen de variables de entorno. Para más información, consulte Configure access credentials in PHP.

Código de ejemplo

A continuación se muestra cómo realizar una carga mediante formulario. El proceso consta de los siguientes pasos:

  1. Crear una Post Policy: Especifique el periodo de validez y las condiciones de la solicitud de carga, incluidos el nombre del bucket, la versión de la firma, las credenciales, la fecha de la solicitud y el rango de longitud del cuerpo de la solicitud.

  2. Procesar la directiva de carga: Convierta la directiva de carga a una cadena JSON y codifíquela en Base64.

  3. Generar una clave de firma: Utilice el algoritmo HMAC-SHA256 para generar una clave de firma que incluya la fecha, la región, el servicio y el tipo de solicitud.

  4. Calcular la firma: Use la clave generada para firmar la cadena de la directiva codificada en Base64 y convierta la firma a una cadena hexadecimal.

  5. Construir el cuerpo de la solicitud: Cree un escritor de formularios multipart, especifique en el formulario la clave del objeto, la directiva, la versión de la firma, las credenciales, la fecha de la solicitud y la firma; luego, escriba los datos que desea cargar.

  6. Crear y ejecutar la solicitud: Genere una solicitud HTTP POST y defina los encabezados correspondientes. Envíe la solicitud y compruebe el código de estado de la respuesta para asegurarse de que la operación se completó correctamente.

<?php

// Include the autoload file to load dependencies.
require_once __DIR__ . '/../vendor/autoload.php';

use AlibabaCloud\Oss\V2 as Oss;

// Define and describe command-line parameters.
$optsdesc = [
    "region" => ['help' => 'The region in which the bucket is located.', 'required' => True], // (Required)Region in which the bucket is located.
    "bucket" => ['help' => 'The name of the bucket', 'required' => True], // (Required) Bucket name.
    "key" => ['help' => 'The name of the object', 'required' => True], // (Required) Object name.
];

// Convert the descriptions to a list of long options required by getopt.
// Add a colon (:) to the end of each parameter to indicate that a value is required.
$longopts = \array_map(function ($key) {
    return "$key:";
}, array_keys($optsdesc));

// Parse the command-line parameters.
$options = getopt("", $longopts);

// Check whether the required parameters are configured.
foreach ($optsdesc as $key => $value) {
    if ($value['required'] === True && empty($options[$key])) {
        $help = $value['help']; // Obtain help information for the parameters.
        echo "Error: the following arguments are required: --$key, $help" . PHP_EOL;
        exit(1); // Exit the program if required parameters are missing
    }
}

// Extract values from parsed parameters
$region = $options["region"]; // The region where the bucket is located
$bucket = $options["bucket"]; // Bucket name
$key = $options["key"];       // Object name
$product = 'oss';             // Fixed as OSS service

// Load credential information from environment variables
// Use EnvironmentVariableCredentialsProvider to read Access Key ID and Access Key Secret from environment variables
$credentialsProvider = new Oss\Credentials\EnvironmentVariableCredentialsProvider();
$cred = $credentialsProvider->getCredentials();

// Data content to be uploaded
$data = 'hi oss'; // Example data, can be replaced with other content in actual use

// Get current UTC time and format it
$utcTime = new DateTime('now', new DateTimeZone('UTC'));
$date = $utcTime->format('Ymd'); // Current date, used for signature calculation
$expiration = clone $utcTime;
$expiration->add(new DateInterval('PT1H')); // Set expiration time to 1 hour later

// Build Policy document
$policyMap = [
    "expiration" => $expiration->format('Y-m-d\TH:i:s.000\Z'), // Policy expiration time
    "conditions" => [
        ["bucket" => $bucket], // Specify bucket name
        ["x-oss-signature-version" => "OSS4-HMAC-SHA256"], // Signature version
        ["x-oss-credential" => sprintf("%s/%s/%s/%s/aliyun_v4_request",
            $cred->getAccessKeyId(), $date, $region, $product)], // Credential information
        ["x-oss-date" => $utcTime->format('Ymd\THis\Z')], // Current timestamp
        // Other conditions
        ["content-length-range", 1, 1024], // File size range limit
        // ["eq", "$success_action_status", "201"], // Optional: specify success status code
        // ["starts-with", "$key", "user/eric/"], // Optional: specify object key prefix
        // ["in", "$content-type", ["image/jpg", "image/png"]], // Optional: specify allowed content types
        // ["not-in", "$cache-control", ["no-cache"]], // Optional: exclude certain cache control headers
    ],
];

// Encode Policy document as JSON string
$jsonOptions = JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE; // Prevent escaping slashes and Unicode characters
$policy = json_encode($policyMap, $jsonOptions);
if (json_last_error() !== JSON_ERROR_NONE) {
    error_log("json_encode fail, err: " . json_last_error_msg()); // Check if JSON encoding failed
    exit(1);
}

// Calculate information needed for signature
$stringToSign = base64_encode($policy); // Base64 encode the Policy
$signingKey = "aliyun_v4" . $cred->getAccessKeySecret(); // Construct signing key
$h1Key = hmacSign($signingKey, $date); // Step 1: Sign the date
$h2Key = hmacSign($h1Key, $region);   // Step 2: Sign the region
$h3Key = hmacSign($h2Key, $product);  // Step 3: Sign the product
$h4Key = hmacSign($h3Key, "aliyun_v4_request"); // Step 4: Sign the request

// Calculate final signature
$signature = hash_hmac('sha256', $stringToSign, $h4Key);

// Build form data for POST request
$bodyWriter = new CURLFileUpload(); // Create form builder instance

// Add fields to the form
$bodyWriter->addField('key', $key); // Object name
$bodyWriter->addField('policy', $stringToSign); // Base64 encoded Policy
$bodyWriter->addField('x-oss-signature-version', 'OSS4-HMAC-SHA256'); // Signature version
$bodyWriter->addField('x-oss-credential', sprintf("%s/%s/%s/%s/aliyun_v4_request",
    $cred->getAccessKeyId(), $date, $region, $product)); // Credential information
$bodyWriter->addField('x-oss-date', $utcTime->format('Ymd\THis\Z')); // Timestamp
$bodyWriter->addField('x-oss-signature', $signature); // Final signature

// Add file content to the form
$bodyWriter->addFileFromString('file', $data); // Upload file content
$postData = $bodyWriter->getFormData(); // Get complete form data

// Send POST request
$client = new \GuzzleHttp\Client(); // Create HTTP client
$response = $client->post(
    sprintf("http://%s.oss-%s.aliyuncs.com/", $bucket, $region), // OSS upload URL
    [
        'headers' => [
            'content-type' => $bodyWriter->getContentType(), // Set Content-Type
        ],
        'body' => $postData // Set request body
    ]
);

// Check response status code
if ($response->getStatusCode() < 200 || $response->getStatusCode() >= 300) {
    echo "Post Object Fail, status code:" . $response->getStatusCode() . ", reason: " . $response->getReasonPhrase() . PHP_EOL;
    exit(1); // Exit the program if status code is not in 2xx range
}

// Print upload result
echo "post object done, status code:" . $response->getStatusCode() . ", request id:" . $response->getHeaderLine('x-oss-request-id') . PHP_EOL;

/**
 * HMAC signature function
 * @param string $key Signing key
 * @param string $data Data to be signed
 * @return string Returns signature result
 */
function hmacSign($key, $data)
{
    return hash_hmac('sha256', $data, $key, true); // Generate HMAC signature using SHA256 algorithm
}

/**
 * Form builder class for generating multipart/form-data format request body
 */
class CURLFileUpload
{
    private $fields = []; // Store regular fields
    private $files = [];  // Store file fields
    private $boundary;    // Separator

    public function __construct()
    {
        $this->boundary = uniqid(); // Generate unique separator
    }

    /**
     * Add regular field
     * @param string $name Field name
     * @param string $value Field value
     */
    public function addField($name, $value)
    {
        $this->fields[$name] = $value;
    }

    /**
     * Add file field
     * @param string $name Field name
     * @param string $content File content
     */
    public function addFileFromString($name, $content)
    {
        $this->files[$name] = [
            'content' => $content,
            'filename' => $name,
            'type' => 'application/octet-stream' // Default MIME type
        ];
    }

    /**
     * Get complete form data
     * @return string Returns request body in multipart/form-data format
     */
    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;
    }

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

Referencias

  • Para consultar un ejemplo completo de carga mediante formulario, revise el ejemplo en GitHub.