如何解决REST API上传视频至Azure Media Service的网关超时问题
Azure Media Services 文件上传 GatewayTimeout 问题解决及成功响应说明
问题原因
你遇到的GatewayTimeout错误,是因为Azure Media Services的Management API不支持直接通过multipart/form-data上传大文件——这类请求会因文件体积大、处理链路长导致网关超时。官方标准流程是先获取Asset的SAS(共享访问签名)URL,再直接将文件上传到Azure Blob存储,而非通过Management API中转。
修复方案
步骤1:获取Asset的可写SAS URL
先调用API生成用于上传的SAS URL,有效期可自行调整:
$subscriptionId = "c219b0b7-cc1d-4cdb-b323-xxxxxxxxxx"; $resourceGroupName = "maxtv2"; $accountName = "maxtv2"; $assetName = "Plan-Details"; $filePath = "./sample.mp4"; // 构造获取SAS URL的请求地址 $sasApiUrl = "https://management.azure.com/subscriptions/{$subscriptionId}/resourceGroups/{$resourceGroupName}/providers/Microsoft.Media/mediaServices/{$accountName}/assets/{$assetName}/listContainerSas?api-version=2023-01-01"; // 请求体:设置权限为写入,有效期1小时 $sasRequestData = json_encode([ "permissions" => "Write", "expiryTime" => date('c', strtotime('+1 hour')) ]); $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $sasApiUrl); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_HTTPHEADER, [ "Authorization: Bearer $accessToken", "Content-Type: application/json" ]); curl_setopt($ch, CURLOPT_POSTFIELDS, $sasRequestData); $sasResponse = curl_exec($ch); if (curl_errno($ch)) { die('获取SAS URL失败: ' . curl_error($ch)); } curl_close($ch); $sasResult = json_decode($sasResponse, true); if (!isset($sasResult['assetContainerSasUrls'][0])) { die('解析SAS URL失败'); } // 拼接最终的文件上传URL(包含Blob名称和SAS参数) $blobName = basename($filePath); $uploadUrl = $sasResult['assetContainerSasUrls'][0] . "/$blobName?" . parse_url($sasResult['assetContainerSasUrls'][0], PHP_URL_QUERY);
步骤2:通过SAS URL直接上传文件
使用PUT请求上传,适合大文件且避免中转超时:
$fileHandle = fopen($filePath, 'r'); if (!$fileHandle) { die('无法打开文件: ' . $filePath); } $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $uploadUrl); curl_setopt($ch, CURLOPT_PUT, true); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_HTTPHEADER, [ "Content-Type: video/mp4" ]); curl_setopt($ch, CURLOPT_INFILE, $fileHandle); curl_setopt($ch, CURLOPT_INFILESIZE, filesize($filePath)); // 设置客户端超时(根据文件大小调整,示例为5分钟) curl_setopt($ch, CURLOPT_TIMEOUT, 300); $uploadResponse = curl_exec($ch); $httpStatus = curl_getinfo($ch, CURLINFO_HTTP_CODE); if (curl_errno($ch)) { echo '上传错误: ' . curl_error($ch); } else { if ($httpStatus === 201) { echo '文件上传成功'; } else { echo "上传失败,HTTP状态码: $httpStatus,响应内容: $uploadResponse"; } } fclose($fileHandle); curl_close($ch);
额外优化建议
- 大文件分块:如果文件超过100MB,建议使用Blob存储的分块上传(Block Blob),避免单次请求过大导致超时
- 权限校验:确保你的服务主体拥有
Microsoft.Media/mediaServices/assets/listContainerSas/action权限,以及对应存储账户的写入权限 - 超时配置:根据文件大小调整
CURLOPT_TIMEOUT的值,确保客户端不会提前断开连接
文件上传成功的标识
- SAS URL上传方式:成功时返回HTTP 201 Created状态码,响应体为空或包含Blob元数据
- 若使用官方Management API的文件列表接口验证:上传后调用
GET /assets/{assetName}/files接口,会返回包含目标文件的列表,格式示例:
{ "value": [ { "name": "sample.mp4", "properties": { "assetId": "your-asset-id", "created": "2024-05-20T12:34:56Z", "lastModified": "2024-05-20T12:34:56Z", "size": 123456789, "mimeType": "video/mp4" } } ] }
内容的提问来源于stack exchange,提问作者Niyasali
相关产品推荐
相关产品推荐

