Files
g.hnyhua.cn/VodSDK/VodSDK.cs
2026-02-07 15:48:27 +08:00

276 lines
9.8 KiB
C#

using COSXML;
using COSXML.Auth;
using COSXML.Model.Object;
using COSXML.Utils;
using System;
using System.IO;
using System.Threading;
using TencentCloud.Common;
using TencentCloud.Vod.V20180717;
using TencentCloud.Vod.V20180717.Models;
namespace VodSDK
{
public class VodUploadClient
{
private string SecretId;
private string SecretKey;
static private long MinPartSize = 1024 * 1024;
static private long MaxPartNum = 10000;
static public int PoolSize = 10;
static private int retryTime = 3;
public VodUploadClient(string secretId, string secretKey)
{
SecretId = secretId;
SecretKey = secretKey;
}
public VodUploadResponse Upload(string region, VodUploadRequest req)
{
CheckRequest(region, req);
TencentCloud.Common.Credential cred = new TencentCloud.Common.Credential
{
SecretId = SecretId,
SecretKey = SecretKey
};
VodClient vodClient = new VodClient(cred, region);
ApplyUploadResponse applyResp = DoApplyRequest(vodClient, req);
//Console.WriteLine(AbstractModel.ToJsonString(applyResp));
DoUploadAction(applyResp, req);
CommitUploadResponse commitResp = DoCommitRequest(vodClient, applyResp);
//Console.WriteLine(AbstractModel.ToJsonString(commitResp));
VodUploadResponse rsp= AbstractModel.FromJsonString<VodUploadResponse>( AbstractModel.ToJsonString(commitResp));
return rsp;
}
private void CheckRequest(string region, VodUploadRequest req)
{
FileInfo fileInfo = new FileInfo(req.MediaFilePath);
if (string.IsNullOrEmpty(region))
{
throw new VodClientException("lack region");
}
if (string.IsNullOrEmpty(req.MediaFilePath))
{
throw new VodClientException("lack media path");
}
if (!fileInfo.Exists)
{
throw new VodClientException("media path is invalid");
}
if (fileInfo.Extension == "")
{
throw new VodClientException("lack media type");
}
if (!string.IsNullOrEmpty(req.CoverFilePath))
{
FileInfo coverInfo = new FileInfo(req.CoverFilePath);
if (!coverInfo.Exists)
{
throw new VodClientException("cover path is invalid");
}
if (coverInfo.Extension == "")
{
throw new VodClientException("lack cover type");
}
}
}
private ApplyUploadResponse DoApplyRequest(VodClient client, VodUploadRequest req)
{
req.MediaType = System.IO.Path.GetExtension(req.MediaFilePath).Substring(1);
req.MediaName = System.IO.Path.GetFileName(req.MediaFilePath);
if (req.CoverFilePath != null && req.CoverFilePath != "")
{
req.CoverType = System.IO.Path.GetExtension(req.CoverFilePath).Substring(1);
}
TencentCloudSDKException err = null;
for (int i = 0; i < retryTime; i++)
{
try
{
return client.ApplyUpload(req).
ConfigureAwait(false).GetAwaiter().GetResult();
}
catch (TencentCloudSDKException exception)
{
if (exception.RequestId == "")
{
err = exception;
continue;
}
throw exception;
}
}
throw err;
}
private CommitUploadResponse DoCommitRequest(VodClient client, ApplyUploadResponse applyResp)
{
CommitUploadRequest commitReq = new CommitUploadRequest();
commitReq.VodSessionKey = applyResp.VodSessionKey;
TencentCloudSDKException err = null;
for (int i = 0; i < retryTime; i++)
{
try
{
return client.CommitUpload(commitReq).
ConfigureAwait(false).GetAwaiter().GetResult();
}
catch (TencentCloudSDKException exception)
{
if (exception.RequestId == "")
{
err = exception;
continue;
}
throw exception;
}
}
throw err;
}
private void DoUploadAction(ApplyUploadResponse applyResp, VodUploadRequest req)
{
string[] fields = applyResp.StorageBucket.Split('-');
string cosAppId = fields[fields.Length - 1];
CosXmlConfig config = new CosXmlConfig.Builder()
.SetAppid(cosAppId)
.SetRegion(applyResp.StorageRegion)
.SetDebugLog(false)
.SetConnectionLimit(512)
.Build();
DefaultSessionQCloudCredentialProvider qCloudCredentialProvider = new DefaultSessionQCloudCredentialProvider(applyResp.TempCertificate.SecretId, applyResp.TempCertificate.SecretKey,
(long)applyResp.TempCertificate.ExpiredTime, applyResp.TempCertificate.Token);
CosXmlServer cosXml = new CosXmlServer(config, qCloudCredentialProvider);
MultiUpload(cosXml, applyResp.StorageBucket, applyResp.MediaStoragePath, req.MediaFilePath);
if (!string.IsNullOrEmpty(req.CoverFilePath))
{
MultiUpload(cosXml, applyResp.StorageBucket, applyResp.CoverStoragePath, req.CoverFilePath);
}
}
private class UploadOnePart
{
CosXml CosXml;
UploadPartRequest Req;
public Exception partException;
public UploadPartResult Result { get; set; }
public UploadOnePart(CosXml cosXml, UploadPartRequest req)
{
CosXml = cosXml;
Req = req;
}
public void UploadPartResult()
{
try
{
Result = CosXml.UploadPart(Req);
}
catch (Exception e)
{
partException = e;
}
}
}
private void MultiUpload(COSXML.CosXml cosXml, string bucket, string key, string srcPath)
{
try
{
InitMultipartUploadRequest initMultipartUploadRequest = new InitMultipartUploadRequest(bucket, key);
InitMultipartUploadResult initMultipartUploadResult = cosXml.InitMultipartUpload(initMultipartUploadRequest);
string uploadId = initMultipartUploadResult.initMultipartUpload.uploadId;
CompleteMultipartUploadRequest completeMultiUploadRequest = new CompleteMultipartUploadRequest(bucket, key, uploadId);
FileInfo fileInfo = new FileInfo(srcPath);
long contentLength = fileInfo.Length;
long partSize = MinPartSize;
long partNum = (contentLength + partSize - 1) / partSize;
if (partNum > MaxPartNum)
{
partSize = (partNum + MaxPartNum - 1) / MaxPartNum * 1024 * 1024;
partNum = (contentLength + partSize - 1) / partSize;
}
UploadOnePart[] uploadList = new UploadOnePart[PoolSize];
Thread[] workPool = new Thread[PoolSize];
for (int i = 0; i * partSize <= contentLength; i += PoolSize)
{
for (int j = 0; j < PoolSize; j++)
{
if ((i + j) * partSize >= contentLength)
{
break;
}
UploadPartRequest uploadPartRequest = new UploadPartRequest(bucket, key, (int)(i + j + 1), uploadId, srcPath, (i + j) * partSize, partSize);
uploadList[j] = new UploadOnePart(cosXml, uploadPartRequest);
ThreadStart childref = new ThreadStart(uploadList[j].UploadPartResult);
workPool[j] = new Thread(childref);
workPool[j].Start();
}
for (int j = 0; j < PoolSize; j++)
{
if ((i + j) * partSize >= contentLength)
{
break;
}
workPool[j].Join();
if (uploadList[j].partException != null)
{
throw uploadList[i].partException;
}
completeMultiUploadRequest.SetPartNumberAndETag(i + j + 1, uploadList[j].Result.eTag);
}
}
//执行请求
CompleteMultipartUploadResult completeMultiUploadResult = cosXml.CompleteMultiUpload(completeMultiUploadRequest);
}
catch (COSXML.CosException.CosClientException clientEx)
{
throw clientEx;
}
catch (COSXML.CosException.CosServerException serverEx)
{
throw serverEx;
}
}
}
public class VodClientException : Exception
{
public VodClientException(string e) : base(e) { }
}
public class VodUploadRequest:ApplyUploadRequest
{
public string MediaFilePath { get; set; }
public string CoverFilePath { get; set; }
}
public class VodUploadResponse:CommitUploadResponse
{
}
}