更新时间:2025-03-13 GMT+08:00
C#
分段上传C#语言的示例代码,如下所示:
using System.Net;
using System.Net.Http.Headers;
using System.Security.Cryptography;
using System.Text;
using System.Web;
using System.Xml.Linq;
using HuaweiCloud.SDK.Core;
using HuaweiCloud.SDK.Core.Auth;
using HuaweiCloud.SDK.Vod.V1;
using HuaweiCloud.SDK.Vod.V1.Model;
/**
* 分段上传示例
*/
public class PartUploadDemo
{
// 设置缓冲区大小,每次读取文件分段的大小,根据情况自行设定
private const int BuffSize = 1024 * 1024; // 1MB
// 区域
private const string RegionNorth4 = "cn-north-4";
private const string RegionNorth1 = "cn-north-1";
private const string RegionEast2 = "cn-east-2";
// ak/sk
private const string Ak = "";
private const string Sk = "";
public static void Start()
{
// 本地要上传的媒资路径
const string filePath = "";
// 上传媒资文件
UploadFile(filePath);
}
/**
* 分段上传
* @param filePath 上传文件的本地路径
*/
private static void UploadFile(string filePath)
{
// 校验一下文件路径和文件
ValidFile(filePath);
var fileInfo = new FileInfo(filePath);
try
{
// 此处仅以MP4文件示例,其他格式可以参考官网说明
var fileType = "MP4";
var fileContentType = "video/mp4";
// 1.初始化鉴权并获取vodClient
var vodClient = CreateVodClient();
Console.WriteLine("开始创建媒资:" + fileInfo.Name);
// 2.创建点播媒资
var assetResponse = CreateAssetByFileUpload(vodClient, fileInfo.Name, fileInfo.Name, fileType);
// 3.初始化上传任务授权
var initAuthResponse = InitPartUploadAuthority(vodClient, assetResponse, fileContentType);
// 4.初始化上传任务
var uploadId = InitPartUpload(initAuthResponse.SignStr, fileContentType).Result;
// 文件分段计数
var partNumber = 1;
// 记录读取的长度
var bytesRead = 0;
// 7. 读取文件内容,循环5-6步上传所有分段
var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read);
// 创建一个缓冲区
var buffer = new byte[BuffSize];
while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) > 0)
{
// 读取的长度小于缓冲区长度,复制有效长度内数据,用于最后一段
if (bytesRead != BuffSize)
{
var tmp = new byte[bytesRead];
Array.Copy(buffer, tmp, bytesRead);
buffer = tmp;
}
// 先计算MD5哈希值
var hashBytes = MD5.HashData(buffer);
// 再将MD5哈希值转换为Base64字符串
var contentMd5 = Convert.ToBase64String(hashBytes);
//输出Base64字符串
Console.WriteLine("该文件第" + (partNumber) + "段MD5为:" + contentMd5);
// 5.获取上传分段的授权
var partUploadAuthorityResponse =
GetPartUploadAuthority(vodClient, fileContentType, assetResponse, contentMd5, uploadId, partNumber);
// 6.上传分段
var flag = UploadPartFile(partUploadAuthorityResponse.SignStr, buffer, contentMd5).Result;
// 段号自增
partNumber++;
}
fileStream.Close();
// 8.获取已上传分段的授权
var listPartUploadAuthorityResponse = ListUploadedPartAuthority(vodClient, assetResponse, uploadId);
// 9.获取已上传的分段
var partInfo = ListUploadedPart(listPartUploadAuthorityResponse.SignStr).Result;
// 10.获取合并段授权
var mergePartUploadAuthorityResponse = MergeUploadedPartAuthority(vodClient, assetResponse, uploadId);
// 11.合并上传分段
_ = MergeUploadedPart(mergePartUploadAuthorityResponse.SignStr, partInfo).Result;
// 12.确认媒资上传
ConfirmUploaded(vodClient, assetResponse);
Console.WriteLine("创建媒资结束 assetId:" + assetResponse.AssetId);
}
catch (RequestTimeoutException requestTimeoutException)
{
Console.WriteLine(requestTimeoutException.ErrorMessage);
}
catch (ServiceResponseException clientRequestException)
{
Console.WriteLine(clientRequestException.HttpStatusCode);
Console.WriteLine(clientRequestException.RequestId);
Console.WriteLine(clientRequestException.ErrorCode);
Console.WriteLine(clientRequestException.ErrorMessage);
}
catch (ConnectionException connectionException)
{
Console.WriteLine(connectionException.ErrorMessage);
}
catch (Exception exception)
{
Console.WriteLine(exception.Message);
}
}
/**
* 校验文件路径和文件
* @param filePath
*/
private static void ValidFile(string filePath)
{
var fileExists = File.Exists(filePath);
if (!fileExists)
{
// 文件不存在
throw new Exception("文件不存在");
}
}
/**
* 1.构建鉴权
* @return
*/
private static VodClient CreateVodClient()
{
var config = HttpConfig.GetDefaultConfig();
config.IgnoreSslVerification = true;
var auth = new BasicCredentials(Ak, Sk);
var client = VodClient.NewBuilder()
.WithCredential(auth)
.WithRegion(VodRegion.ValueOf(RegionNorth4))
.WithHttpConfig(config)
.Build();
return client;
}
/**
* 2.创建媒资
* @param client
* @param title
* @param videoName
* @param video
* @return
*/
private static CreateAssetByFileUploadResponse CreateAssetByFileUpload(VodClient client, string title,
string videoName,
string videoType)
{
Console.WriteLine("createAssetByFileUpload start");
var req = new CreateAssetByFileUploadRequest
{
Body = new CreateAssetByFileUploadReq()
{
Title = title,
VideoName = videoName,
VideoType = videoType
}
};
// 调用创建媒资
var response = client.CreateAssetByFileUpload(req);
Console.WriteLine("createAssetByFileUpload end; createAssetResponse:" + response);
return response;
}
/**
* 3.获取初始化上传任务授权
* @param client
* @param assetResponse
* @param fileContentType
*/
private static ShowAssetTempAuthorityResponse InitPartUploadAuthority(VodClient client,
CreateAssetByFileUploadResponse assetResponse,
string fileContentType)
{
Console.WriteLine("获取初始化上传任务授权 initPartUploadAuthority start");
// 设置参数
var request = new ShowAssetTempAuthorityRequest
{
HttpVerb = "POST",
Bucket = assetResponse.Target.Bucket,
ObjectKey = assetResponse.Target.Object,
ContentType = fileContentType
};
//发送初始化请求
var response = client.ShowAssetTempAuthority(request);
Console.WriteLine("获取初始化上传任务授权 initPartUploadAuthority end; response" + response);
return response;
}
/**
* 4.初始化分段上传
* @param signStr
* @param contentType
* @return
*/
private static async Task<string?> InitPartUpload(string signStr, string contentType)
{
Console.WriteLine("初始化分段上传 initPartUpload start");
using var client = new HttpClient();
var content = new ByteArrayContent([]);
content.Headers.ContentType = new MediaTypeHeaderValue(contentType);
var response = await client.PostAsync(signStr, content);
// 确保请求成功
response.EnsureSuccessStatusCode();
var responseBody = await response.Content.ReadAsStringAsync();
Console.WriteLine(responseBody);
var root = XElement.Parse(responseBody);
var ns = root.Name.Namespace;
var uploadId = root.Element("{" + ns + "}UploadId")?.Value;
Console.WriteLine("初始化分段上传 initPartUpload end; UploadId:" + uploadId);
return uploadId;
}
/**
* 5.获取分段上传任务授权
* @param client
* @param fileContentType
* @param assetResponse
* @param contentMd5
* @param uploadId
* @param partNumber
* @return
*/
private static ShowAssetTempAuthorityResponse GetPartUploadAuthority(VodClient client,
string fileContentType, CreateAssetByFileUploadResponse assetResponse, string contentMd5,
string uploadId, int partNumber)
{
// Thread.Sleep(2000);
Console.WriteLine("获取分段上传任务授权 GetPartUploadAuthority start:" + partNumber);
// 设置参数
var request = new ShowAssetTempAuthorityRequest
{
HttpVerb = "PUT",
Bucket = assetResponse.Target.Bucket,
ObjectKey = assetResponse.Target.Object,
ContentType = fileContentType,
// ContentMd5 = contentMd5,
ContentMd5 = HttpUtility.UrlEncode(contentMd5),
UploadId = uploadId,
PartNumber = partNumber
};
Console.WriteLine(WebUtility.UrlEncode(contentMd5));
var response = client.ShowAssetTempAuthority(request);
Console.WriteLine("获取分段上传任务授权 GetPartUploadAuthority end; response" + partNumber + "; response: " + response + "\n");
return response;
}
/**
* 6.上传分段
* @param signStr
* @param fileByte
* @param contentMd5
*/
public static async Task<Boolean> UploadPartFile(string signStr, byte[] fileByte, string contentMd5)
{
Console.WriteLine("上传分段 uploadPartFile start");
HttpClient client = new HttpClient();
HttpContent content = new ByteArrayContent(fileByte);
content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
content.Headers.Add("Content-MD5", contentMd5);
HttpResponseMessage response = await client.PutAsync(signStr, content);
Console.WriteLine("上传分段 response:" + response);
response.EnsureSuccessStatusCode(); // 确保请求成功
var responseBody = await response.Content.ReadAsStringAsync();
Console.WriteLine("上传分段 uploadPartFile end; response:" + responseBody);
return true;
}
/**
* 8.获取列举上传分段的授权
* @param client
* @param assetResponse
* @param uploadId
* @return
*/
private static ShowAssetTempAuthorityResponse ListUploadedPartAuthority(VodClient client,
CreateAssetByFileUploadResponse assetResponse, string? uploadId)
{
Console.WriteLine("获取列举已上传段的授权 listUploadedPartAuthority start");
var request = new ShowAssetTempAuthorityRequest
{
HttpVerb = "GET",
Bucket = assetResponse.Target.Bucket,
ObjectKey = assetResponse.Target.Object,
UploadId = uploadId
};
var response = client.ShowAssetTempAuthority(request);
Console.WriteLine("获取列举已上传段的授权 listUploadedPartAuthority end; response: " + response);
return response;
}
/**
* 9.查询已上传的分段
* @param signStr
* @return
*/
private static async Task<string> ListUploadedPart(string signStr)
{
Console.WriteLine("查询已上传的分段 listUploadedPart start");
var partNumberMarker = 0;
var mergerRoot = new XElement("CompleteMultipartUpload");
while (true)
{
// 列举分段
using var client = new HttpClient();
var response = await client.GetAsync(signStr + "&part-number-marker=" + partNumberMarker);
response.EnsureSuccessStatusCode();
var responseBody = await response.Content.ReadAsStringAsync();
Console.WriteLine(responseBody);
var root = XElement.Parse(responseBody);
var ns = root.Name.Namespace;
var partNodes = root.Elements("{" + ns + "}Part");
var partNumberMarkerElement = root.Element("{" + ns + "}NextPartNumberMarker");
foreach (var partNode in partNodes)
{
var partNumberNode = partNode.Element("{" + ns + "}PartNumber");
var partNumber = partNumberNode?.Value;
var eTagNode = partNode.Element("{" + ns + "}ETag");
var etag = eTagNode?.Value;
var part = new XElement("Part");
mergerRoot.Add(part);
part.Add(new XElement("PartNumber", partNumber));
part.Add(new XElement("ETag", etag));
}
partNumberMarker = Convert.ToInt32(partNumberMarkerElement?.Value);
if (partNumberMarker == 0 || partNumberMarker % 1000 != 0)
{
break;
}
}
Console.WriteLine(mergerRoot.ToString());
Console.WriteLine("查询已上传的分段 listUploadedPart end");
return mergerRoot.ToString();
}
/**
* 10.获取合并段授权
* @param client
* @param assetResponse
* @param uploadId
* @return
*/
private static ShowAssetTempAuthorityResponse MergeUploadedPartAuthority(VodClient client,
CreateAssetByFileUploadResponse assetResponse, string? uploadId)
{
Console.WriteLine("获取合并段授权 mergeUploadedPartAuthority start");
var request = new ShowAssetTempAuthorityRequest
{
HttpVerb = "POST",
Bucket = assetResponse.Target.Bucket,
ObjectKey = assetResponse.Target.Object,
UploadId = uploadId
};
var response = client.ShowAssetTempAuthority(request);
Console.WriteLine("获取合并段授权 mergeUploadedPartAuthority end; response: " + response);
return response;
}
/**
* 11.合并分段
*/
public static async Task<Boolean> MergeUploadedPart(string signStr, string partInfo)
{
Console.WriteLine("合并分段 mergeUploadedPart start");
using var client = new HttpClient();
// 请求消息头中增加"content-Type", 值设置为"application/xml"
HttpContent content = new StringContent(partInfo);
content.Headers.ContentType = new MediaTypeHeaderValue("application/xml");
var response = await client.PostAsync(signStr, content);
var responseBody = await response.Content.ReadAsStringAsync();
Console.WriteLine(responseBody);
response.EnsureSuccessStatusCode();
Console.WriteLine("合并分段 mergeUploadedPart end");
return true;
}
/**
* 确认上传完成
*/
private static void ConfirmUploaded(VodClient client, CreateAssetByFileUploadResponse assetResponse)
{
Console.WriteLine("确认上传完成 confirmUploaded start");
var request = new ConfirmAssetUploadRequest
{
Body = new ConfirmAssetUploadReq()
{
Status = ConfirmAssetUploadReq.StatusEnum.FromValue("CREATED"),
AssetId = assetResponse.AssetId
}
};
var response = client.ConfirmAssetUpload(request);
Console.WriteLine("上传完成, assetId: " + response);
}
}
父主题: 分段上传代码示例