276 lines
9.8 KiB
C#
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
|
|
{
|
|
}
|
|
} |