Updated on 2024-12-16 GMT+08:00

PHP

Sample code of multipart upload using PHP:

<?php
namespace HuaweiCloud\SDK\Vod\V1\Model;

use DOMDocument;
use DOMException;
use Exception;

require_once "vendor/autoload.php";
use HuaweiCloud\SDK\Core\Auth\BasicCredentials;
use HuaweiCloud\SDK\Core\Http\HttpConfig;
use HuaweiCloud\SDK\Vod\V1\VodClient;

// Region
const region_north1 = 'cn-north-1';
const region_north4 = 'cn-north-4';
const region_east2 = 'cn-east-2';

// ak/sk
const ak = "";
const sk = "";

const projectId = "";

const endpoint = "https://vod." . region_north4 . ".myhuaweicloud.com";

// Set the buffer size as needed, that is, the size of the file part read each time.
// 1M
const bufferSize = 1024 * 1024;

main();

/*
 * Example of multipart upload
 */
function main(): void
{
    // Path of the local media asset to be uploaded
    $filePath = "";

    // Upload the media asset.
    partUpload($filePath);
}

/**
 * Multipart upload
 * @param $filePath: local path where the file to be uploaded is
 * @return void
 */
function partUpload(string $filePath)
{
    $handle = fopen($filePath, "r");
    if(!$handle){
        throw new Exception("The file cannot be opened.");
    }
    try {
        $fileName = basename($filePath);

        // An MP4 file is used as an example. For details about other formats, see the official website.
        $fileType = "MP4";
        $fileContentType = "video/mp4";

        // 1. Initialize authentication and obtain vodClient.
        $vodClient = createVodClient();
        echo "Start to create a media asset:" . $fileName . "\n";
        // 2. Create a VOD media asset.
        $assetResponse = createAsset($vodClient, $fileName, $fileName, $fileType);
        // 3. Obtain authorization for initializing an upload task.
        $initAuthResponse = initPartUploadAuthority($vodClient, $assetResponse, $fileContentType);
        // 4. Initialize the upload task.
        $uploadId = initPartUpload($initAuthResponse->getSignStr(), $fileContentType);
        // Count the number of file parts.
        $partNumber = 1;

        // 7. Read the file content and repeat steps 5 and 6 to upload all parts.
        while (!feof($handle)) {
            $content = fread($handle, bufferSize);
            // Perform MD5 encoding and then Base64 encoding.
            $md5Hash = md5($content);
            echo "md5:". $md5Hash ."\n";
            $hexString = hex2bin($md5Hash);
            $contentMd5 = base64_encode($hexString);
            echo "" . $partNumber . " part of the file: contentMd5:" . $contentMd5 . "\n";

            // 5. Obtain authorization for multipart upload.
            $partUploadAuthorityResponse = getPartUploadAuthority($vodClient, $fileContentType, $assetResponse, $contentMd5, $uploadId, $partNumber);
            // 6. Upload parts.
            uploadPartFile($partUploadAuthorityResponse->getSignStr(), $content, $contentMd5);

            // The part number automatically increments by one.
            $partNumber++;
        }
        fclose($handle);

        // 8. Obtain authorization for obtaining uploaded parts.
        $listPartUploadAuthorityResponse = listUploadedPartAuthority($vodClient, $assetResponse, $uploadId);
        // 9. Obtain uploaded parts.
        $partInfo = listUploadedPart($listPartUploadAuthorityResponse->getSignStr());
        // 10. Obtain authorization for merging parts.
        $mergePartUploadAuthorityResponse = mergeUploadedPartAuthority($vodClient, $assetResponse, $uploadId);
        // 11. Merge uploaded parts.
        mergeUploadedPart($mergePartUploadAuthorityResponse->getSignStr(), $partInfo);
        // 12. Confirm media asset upload.
        confirmUploaded($vodClient, $assetResponse);

        echo "Media asset created assetId:" . $assetResponse->getAssetId() . "\n";

    } catch (Exception $e) {
        echo $e;
    }
}

/**
 * 1. Construct authentication.
 * @return VodClient
 */
function createVodClient(): VodClient
{
    $credentials = new BasicCredentials(ak, sk, projectId);
    $config = HttpConfig::getDefaultConfig();
    $config->setIgnoreSslVerification(true);

    $client = VodClient::newBuilder(new VodClient)
        ->withHttpConfig($config)
        ->withEndpoint(endpoint)
        ->withCredentials($credentials)
        ->build();
    return $client;
}

/**
 * 2. Create a media asset.
 * @param VodClient $vodClient
 * @param string $videoName
 * @param string $title
 * @param string $videoType
 * @return CreateAssetByFileUploadResponse $response
 */
function createAsset(VodClient $vodClient, string $videoName, string $title, string $videoType): CreateAssetByFileUploadResponse
{
    $request = new CreateAssetByFileUploadRequest();
    $body = new CreateAssetByFileUploadReq();
    $body->setVideoName($videoName);
    $body->setTitle($title);
    $body->setVideoType($videoType);
    $request->setBody($body);
    $response = $vodClient->createAssetByFileUpload($request);
    echo $response . "\n";
    return $response;
}

/**
 * 3. Obtain authorization for initializing an upload task.
 * @param VodClient $client
 * @param CreateAssetByFileUploadResponse $assetResponse
 * @param string $fileContentType
 * @return ShowAssetTempAuthorityResponse
 */
function initPartUploadAuthority(VodClient $client, CreateAssetByFileUploadResponse $assetResponse, string $fileContentType): ShowAssetTempAuthorityResponse
{
    echo "Obtain authorization for initializing an upload task. initPartUploadAuthority start\n";
    $request = new ShowAssetTempAuthorityRequest();
    // Configure parameters.
    $request->setHttpVerb("POST");
    $request->setBucket($assetResponse->getTarget()->getBucket());
    $request->setObjectKey($assetResponse->getTarget()->getObject());
    $request->setContentType($fileContentType);
    // Send an initialization request.
    $response = $client->showAssetTempAuthority($request);
    echo "Obtain authorization for initializing an upload task. end; response:" . $response . "\n\n";
    return $response;
}

/**
 * 4. Initialize multipart upload.
 * @param string $signStr
 * @param string $contentType
 * @return string|null
 */
function initPartUpload(string $signStr, string $contentType): string
{
    echo "Initialize multipart upload. initPartUpload start\n";
    // Initialize the cURL session.
    $ch = curl_init();
    // Configure the cURL.
    curl_setopt($ch, CURLOPT_URL, $signStr);
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_HTTPHEADER, array(
        "Content-Type: " . $contentType // Set the request header.
    ));
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // Verify the cURL peer certificate. (Generally, only this item is required.)
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); // Check whether the server SSL certificate contains a common name.
    curl_setopt($ch, CURLOPT_SSLVERSION, 0);  // Transfer a long parameter that contains the SSL version.

    // Execute the cURL session.
    $response = curl_exec($ch);
    if (curl_errno($ch)) {
        echo 'cURL Error: ' . curl_error($ch);
    } else {
        // Print the response content.
        echo $response;
    }

    echo $response . "\n";
    $initDom = new DOMDocument();
    $initDom->loadXML($response);
    curl_close($ch);
    $UploadIdNode = $initDom->getElementsByTagName("UploadId");
    $uploadId = $UploadIdNode->item(0)->nodeValue;
    echo "Initialize multipart upload. initPartUpload end; UploadId:" . $uploadId . "\n\n";
    return $uploadId;
}

/**
 * 5. Obtain authorization for multipart upload.
 * @param VodClient $client
 * @param string $fileContentType
 * @param CreateAssetByFileUploadResponse $assetResponse
 * @param string $contentMd5
 * @param string $uploadId
 * @param int $partNumber
 * @return ShowAssetTempAuthorityResponse
 */
function getPartUploadAuthority(VodClient $client, string $fileContentType, CreateAssetByFileUploadResponse $assetResponse,
                                string $contentMd5, string $uploadId, int $partNumber): ShowAssetTempAuthorityResponse
{
    echo "Obtain authorization for multipart upload. getPartUploadAuthority start; partNumber:" . $partNumber . "\n";
    $request = new ShowAssetTempAuthorityRequest();
    $request->setHttpVerb("PUT");
    $request->setBucket($assetResponse->getTarget()->getBucket());
    $request->setObjectKey($assetResponse->getTarget()->getObject());
    $request->setContentType($fileContentType);
    $request->setContentMd5($contentMd5);
    $request->setUploadId($uploadId);
    $request->setPartNumber($partNumber);
    $response = $client->showAssetTempAuthority($request);
    echo "Obtain authorization for multipart upload. getPartUploadAuthority end; partNumber:" . $partNumber . "\n";
    return $response;
}

/**
 * 6. Upload parts.
 * @param string $signStr
 * @param string $fileByte
 * @param string $contentMd5
 * @return void
 * @throws Exception
 */
function uploadPartFile(string $signStr, $fileByte, string $contentMd5)
{
    echo "Upload parts. uploadPartFile start\n";
//    echo $fileByte . "\n";
    // Initialize the cURL session.
    $ch = curl_init();
    // Configure the cURL.
    curl_setopt($ch, CURLOPT_URL, $signStr);
    curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PUT');
    curl_setopt($ch, CURLOPT_POSTFIELDS, $fileByte);
    curl_setopt($ch, CURLOPT_HTTPHEADER, array(
        "Content-MD5: " . $contentMd5,
        "Content-Type: application/octet-stream"
    ));
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // Verify the cURL peer certificate. (Generally, only this item is required.)
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); // Check whether the server SSL certificate contains a common name.
    curl_setopt($ch, CURLOPT_SSLVERSION, 0);  // Transfer a long parameter that contains the SSL version.
    // Execute the cURL session.
    $response = curl_exec($ch);
    if (curl_errno($ch)) {
        echo 'cURL Error: ' . curl_error($ch);
        // Print the response content.
        echo $response . "\n";
        throw new Exception("Upload failed.");
    }
    // End the session.
    curl_close($ch);
    echo "Upload parts. uploadPartFile end;\n\n";
}

/**
 * 8. Obtain authorization for listing uploaded parts.
 * @param VodClient $client
 * @param CreateAssetByFileUploadResponse $assetResponse
 * @param string $uploadId
 * @return ShowAssetTempAuthorityResponse
 */
function listUploadedPartAuthority(VodClient $client, CreateAssetByFileUploadResponse $assetResponse, string $uploadId):ShowAssetTempAuthorityResponse
{
    echo "Obtain authorization for listing uploaded parts. listUploadedPartAuthority start\n";
    $request = new ShowAssetTempAuthorityRequest();
    $request->setHttpVerb("GET");
    $request->setBucket($assetResponse->getTarget()->getBucket());
    $request->setObjectKey($assetResponse->getTarget()->getObject());
    $request->setUploadId($uploadId);
    $response = $client->showAssetTempAuthority($request);
    echo "Obtain authorization for listing uploaded parts. listUploadedPartAuthority end; response:" . $response . "\n";
    return $response;
}

/**
 * 9. Query uploaded parts.
 * @param string $signStr
 * @return false|string
 * @throws DOMException
 */
function listUploadedPart(string $signStr): false|string
{
    echo "Query uploaded parts. listUploadedPart start\n";
    $partNumberMarker = 0;
    $compDom = new DOMDocument();
    $root = $compDom->createElement("CompleteMultipartUpload");
    $compDom->appendChild($root);
    while(true)
    {
        // Initialize the cURL session.
        $ch = curl_init();
        // Configure the cURL.
        curl_setopt($ch, CURLOPT_URL, $signStr . "&part-number-marker=" . $partNumberMarker);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // Verify the cURL peer certificate. (Generally, only this item is required.)
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); // Check whether the server SSL certificate contains a common name.
        curl_setopt($ch, CURLOPT_SSLVERSION, 0);  // Transfer a long parameter that contains the SSL version.

        // Execute the cURL session.
        $response = curl_exec($ch);
        if (curl_errno($ch)) {
            echo 'cURL Error: ' . curl_error($ch);
        } else {
            // Print the response content.
            echo $response . "\n";
        }
        // End the cURL session.
        curl_close($ch);
        $listDom = new DOMDocument();
        $listDom->loadXML($response);
        $nextPartNumberMarkerNode = $listDom->getElementsByTagName("NextPartNumberMarker");
        $partNodes = $listDom->getElementsByTagName("Part");
        foreach($partNodes as $partNode)
        {
            $partNumberNode = $partNode->getElementsByTagName("PartNumber");
            $partNumber = $partNumberNode->item(0)->nodeValue;
//            echo $partNumber . "\n";
            $eTagNode = $partNode->getElementsByTagName("ETag");
            $eTag = $eTagNode->item(0)->nodeValue;
//            echo $eTag . "\n";
            try{
                $part = $compDom->createElement("Part");
                $part->appendChild($compDom->createElement("PartNumber", $partNumber));
                $part->appendChild($compDom->createElement("ETag", $eTag));
                $root->appendChild($part);
            } catch (DOMException $e){
                echo $e->getMessage();
            }
        }
        $partNumberMarker = $nextPartNumberMarkerNode->item(0)->nodeValue;
        if($partNumberMarker % 1000 != 0 || $partNumberMarker == 0)
        {
            break;
        }
    }
    $partInfo = $compDom->saveXML();
    echo $partInfo . "\n";
    echo "Query uploaded parts. listUploadedPart end\n\n";
    return $partInfo;
}

/**
 * 10. Obtain authorization for merging parts.
 * @param VodClient $client
 * @param CreateAssetByFileUploadResponse $assetResponse
 * @param string $uploadId
 * @return ShowAssetTempAuthorityResponse
 */
function mergeUploadedPartAuthority(VodClient $client, CreateAssetByFileUploadResponse $assetResponse, string $uploadId):ShowAssetTempAuthorityResponse
{
    echo "Obtain authorization for merging parts. mergeUploadedPartAuthority start\n";
    $request = new ShowAssetTempAuthorityRequest();
    $request->setHttpVerb("POST");
    $request->setBucket($assetResponse->getTarget()->getBucket());
    $request->setObjectKey($assetResponse->getTarget()->getObject());
    $request->setUploadId($uploadId);
    $response = $client->showAssetTempAuthority($request);
    echo "Obtain authorization for merging parts. mergeUploadedPartAuthority end; response:" . $response . "\n";
    return $response;
}

/**
 * 11. Merge parts.
 * @param string $signStr
 * @param string $partInfo
 * @return void
 */
function mergeUploadedPart(string $signStr, string $partInfo)
{
    echo "Merge parts. mergeUploadedPart start\n";
    // Initialize the cURL session.
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $signStr);
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $partInfo);
    // Add Content-Type to the request header and set the value to application/xml.
    curl_setopt($ch, CURLOPT_HTTPHEADER, array(
        "Content-Type: application/xml"
    ));
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // Verify the cURL peer certificate. (Generally, only this item is required.)
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); // Check whether the server SSL certificate contains a common name.
    curl_setopt($ch, CURLOPT_SSLVERSION, 0);  // Transfer a long parameter that contains the SSL version.
    // Execute the cURL session.
    $response = curl_exec($ch);
    if (curl_errno($ch)) {
        echo 'cURL Error: ' . curl_error($ch);
    } else {
        // Print the response content.
        echo $response . "\n";
    }
    // End the session.
    curl_close($ch);
    echo "Merge parts. mergeUploadedPart end\n";
}

/**
 * 12. Confirm the upload completion.
 * @param VodClient $client
 * @param CreateAssetByFileUploadResponse $assetResponse
 * @return void
 */
function confirmUploaded(VodClient $client, CreateAssetByFileUploadResponse $assetResponse): void
{
    echo "Confirm the upload completion. confirmUploadedPart start\n";
    $request = new ConfirmAssetUploadRequest();
    $body = new ConfirmAssetUploadReq();
    $body->setStatus("CREATED");
    $body->setAssetId($assetResponse->getAssetId());
    $request->setBody($body);
    $response = $client->confirmAssetUpload($request);
    echo "Uploaded. confirmUploadedPart end; response:" . $response . "\n";
}