更新时间:2024-12-12 GMT+08:00
分享

PHP

分段上传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;

// 区域
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";

// 设置缓冲区大小,每次读取文件分段的大小,根据情况自行设定
// 1M
const bufferSize = 1024 * 1024;

main();

/*
 * 分段上传示例
 */
function main(): void
{
    // 本地要上传的媒资路径
    $filePath = "";

    // 上传媒资文件
    partUpload($filePath);
}

/**
 * 分段上传
 * @param $filePath 传文件的本地路径
 * @return void
 */
function partUpload(string $filePath)
{
    $handle = fopen($filePath, "r");
    if(!$handle){
        throw new Exception("无法打开文件!");
    }
    try {
        $fileName = basename($filePath);

        // 此处仅以MP4文件示例,其他格式可以参考官网说明
        $fileType = "MP4";
        $fileContentType = "video/mp4";

        // 1.初始化鉴权并获取vodClient
        $vodClient = createVodClient();
        echo "开始创建媒资:" . $fileName . "\n";
        // 2.创建点播媒资
        $assetResponse = createAsset($vodClient, $fileName, $fileName, $fileType);
        // 3.获取初始化上传任务授权
        $initAuthResponse = initPartUploadAuthority($vodClient, $assetResponse, $fileContentType);
        // 4.初始化上传任务
        $uploadId = initPartUpload($initAuthResponse->getSignStr(), $fileContentType);
        // 文件分段计数
        $partNumber = 1;

        // 7.读取文件内容,循环5-6步上传所有分段
        while (!feof($handle)) {
            $content = fread($handle, bufferSize);
            // 先md5,再base64
            $md5Hash = md5($content);
            echo "md5:". $md5Hash ."\n";
            $hexString = hex2bin($md5Hash);
            $contentMd5 = base64_encode($hexString);
            echo "该文件第" . $partNumber . "段contentMd5:" . $contentMd5 . "\n";

            // 5.获取上传分段的授权
            $partUploadAuthorityResponse = getPartUploadAuthority($vodClient, $fileContentType, $assetResponse, $contentMd5, $uploadId, $partNumber);
            // 6.上传分段
            uploadPartFile($partUploadAuthorityResponse->getSignStr(), $content, $contentMd5);

            //段号自增
            $partNumber++;
        }
        fclose($handle);

        // 8.获取已上传分段的授权
        $listPartUploadAuthorityResponse = listUploadedPartAuthority($vodClient, $assetResponse, $uploadId);
        // 9.获取已上传的分段
        $partInfo = listUploadedPart($listPartUploadAuthorityResponse->getSignStr());
        // 10.获取合并段授权
        $mergePartUploadAuthorityResponse = mergeUploadedPartAuthority($vodClient, $assetResponse, $uploadId);
        // 11.合并上传分段
        mergeUploadedPart($mergePartUploadAuthorityResponse->getSignStr(), $partInfo);
        // 12.确认媒资上传
        confirmUploaded($vodClient, $assetResponse);

        echo "创建媒资结束 assetId:" . $assetResponse->getAssetId() . "\n";

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

/**
 * 1.构建鉴权
 * @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.创建媒资
 * @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.获取初始化上传任务授权
 * @param VodClient $client
 * @param CreateAssetByFileUploadResponse $assetResponse
 * @param string $fileContentType
 * @return ShowAssetTempAuthorityResponse
 */
function initPartUploadAuthority(VodClient $client, CreateAssetByFileUploadResponse $assetResponse, string $fileContentType): ShowAssetTempAuthorityResponse
{
    echo "获取初始化上传任务授权 initPartUploadAuthority start\n";
    $request = new ShowAssetTempAuthorityRequest();
    // 设置参数
    $request->setHttpVerb("POST");
    $request->setBucket($assetResponse->getTarget()->getBucket());
    $request->setObjectKey($assetResponse->getTarget()->getObject());
    $request->setContentType($fileContentType);
    // 发送初始化请求
    $response = $client->showAssetTempAuthority($request);
    echo "获取初始化上传任务授权 end; response:" . $response . "\n\n";
    return $response;
}

/**
 * 4.初始化分段上传
 * @param string $signStr
 * @param string $contentType
 * @return string|null
 */
function initPartUpload(string $signStr, string $contentType): string
{
    echo "初始化分段上传 initPartUpload start\n";
    // 初始化cURL会话
    $ch = curl_init();
    //设置cURL选项
    curl_setopt($ch, CURLOPT_URL, $signStr);
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_HTTPHEADER, array(
        "Content-Type: " . $contentType // 设置请求头
    ));
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); //验证curl对等证书(一般只要此项)
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); //检查服务器SSL证书中是否存在一个公用名
    curl_setopt($ch, CURLOPT_SSLVERSION, 0);  //传递一个包含SSL版本的长参数。

    // 执行cURL会话
    $response = curl_exec($ch);
    if (curl_errno($ch)) {
        echo 'cURL Error: ' . curl_error($ch);
    } else {
        // 打印响应内容
        echo $response;
    }

    echo $response . "\n";
    $initDom = new DOMDocument();
    $initDom->loadXML($response);
    curl_close($ch);
    $UploadIdNode = $initDom->getElementsByTagName("UploadId");
    $uploadId = $UploadIdNode->item(0)->nodeValue;
    echo "初始化分段上传 initPartUpload end; UploadId:" . $uploadId . "\n\n";
    return $uploadId;
}

/**
 * 5.获取分段上传授权
 * @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 "获取分段上传授权 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 "获取分段上传授权 getPartUploadAuthority end; partNumber:" . $partNumber . "\n";
    return $response;
}

/**
 * 6.上传分段
 * @param string $signStr
 * @param string $fileByte
 * @param string $contentMd5
 * @return void
 * @throws Exception
 */
function uploadPartFile(string $signStr, $fileByte, string $contentMd5)
{
    echo "上传分段 uploadPartFile start\n";
//    echo $fileByte . "\n";
    // 初始化cURL会话
    $ch = curl_init();
    // 设置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); //验证curl对等证书(一般只要此项)
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); //检查服务器SSL证书中是否存在一个公用名
    curl_setopt($ch, CURLOPT_SSLVERSION, 0);  //传递一个包含SSL版本的长参数。
    // 执行cURL会话
    $response = curl_exec($ch);
    if (curl_errno($ch)) {
        echo 'cURL Error: ' . curl_error($ch);
        // 打印响应内容
        echo $response . "\n";
        throw new Exception("上传失败!");
    }
    // 关闭会话
    curl_close($ch);
    echo "上传分段 uploadPartFile end;\n\n";
}

/**
 * 8.获取列举已上传段的授权
 * @param VodClient $client
 * @param CreateAssetByFileUploadResponse $assetResponse
 * @param string $uploadId
 * @return ShowAssetTempAuthorityResponse
 */
function listUploadedPartAuthority(VodClient $client, CreateAssetByFileUploadResponse $assetResponse, string $uploadId):ShowAssetTempAuthorityResponse
{
    echo "获取列举已上传段的授权 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 "列举已上传段的授权 listUploadedPartAuthority end; response:" . $response . "\n";
    return $response;
}

/**
 * 9.查询已上传的分段
 * @param string $signStr
 * @return false|string
 * @throws DOMException
 */
function listUploadedPart(string $signStr): false|string
{
    echo "查询已上传的分段 listUploadedPart start\n";
    $partNumberMarker = 0;
    $compDom = new DOMDocument();
    $root = $compDom->createElement("CompleteMultipartUpload");
    $compDom->appendChild($root);
    while(true)
    {
        // 初始化cURL会话
        $ch = curl_init();
        // 设置cURL选项
        curl_setopt($ch, CURLOPT_URL, $signStr . "&part-number-marker=" . $partNumberMarker);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); //验证curl对等证书(一般只要此项)
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); //检查服务器SSL证书中是否存在一个公用名
        curl_setopt($ch, CURLOPT_SSLVERSION, 0);  //传递一个包含SSL版本的长参数。

        // 执行cURL会话
        $response = curl_exec($ch);
        if (curl_errno($ch)) {
            echo 'cURL Error: ' . curl_error($ch);
        } else {
            // 打印响应内容
            echo $response . "\n";
        }
        // 关闭cURL会话
        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 "查询已上传的分段 listUploadedPart end\n\n";
    return $partInfo;
}

/**
 * 10.获取合并段授权
 * @param VodClient $client
 * @param CreateAssetByFileUploadResponse $assetResponse
 * @param string $uploadId
 * @return ShowAssetTempAuthorityResponse
 */
function mergeUploadedPartAuthority(VodClient $client, CreateAssetByFileUploadResponse $assetResponse, string $uploadId):ShowAssetTempAuthorityResponse
{
    echo "获取合并段授权 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 "获取合并段授权 mergeUploadedPartAuthority end; response:" . $response . "\n";
    return $response;
}

/**
 * 11.合并分段
 * @param string $signStr
 * @param string $partInfo
 * @return void
 */
function mergeUploadedPart(string $signStr, string $partInfo)
{
    echo "合并分段 mergeUploadedPart start\n";
    // 初始化cURL会话
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $signStr);
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $partInfo);
    // 请求消息头中增加"Content-Type",值设置为"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); //验证curl对等证书(一般只要此项)
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); //检查服务器SSL证书中是否存在一个公用名
    curl_setopt($ch, CURLOPT_SSLVERSION, 0);  //传递一个包含SSL版本的长参数。
    // 执行cURL会话
    $response = curl_exec($ch);
    if (curl_errno($ch)) {
        echo 'cURL Error: ' . curl_error($ch);
    } else {
        // 打印响应内容
        echo $response . "\n";
    }
    // 关闭会话
    curl_close($ch);
    echo "合并分段 mergeUploadedPart end\n";
}

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

相关文档