本文导读
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); } }
父主题: 分段上传代码示例