首次推送
This commit is contained in:
571
COSXML/Transfer/COSXMLCopyTask.cs
Normal file
571
COSXML/Transfer/COSXMLCopyTask.cs
Normal file
@@ -0,0 +1,571 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using COSXML.Model.Tag;
|
||||
using COSXML.Model.Object;
|
||||
using COSXML.Utils;
|
||||
using COSXML.Model;
|
||||
using COSXML.CosException;
|
||||
using COSXML.Log;
|
||||
using COSXML.Common;
|
||||
/**
|
||||
* Copyright (c) 2018 Tencent Cloud. All rights reserved.
|
||||
* 11/29/2018 5:02:22 PM
|
||||
* bradyxiao
|
||||
*/
|
||||
namespace COSXML.Transfer
|
||||
{
|
||||
public sealed class COSXMLCopyTask : COSXMLTask, OnMultipartUploadStateListener
|
||||
{
|
||||
private long divisionSize;
|
||||
private long sliceSize;
|
||||
private CopySourceStruct copySource;
|
||||
|
||||
private HeadObjectRequest headObjectRequest;
|
||||
private DeleteObjectRequest deleteObjectRequest;
|
||||
private long sourceSize;
|
||||
|
||||
private CopyObjectRequest copyObjectRequest;
|
||||
|
||||
private Object syncExit = new Object();
|
||||
private bool isExit = false;
|
||||
|
||||
private InitMultipartUploadRequest initMultiUploadRequest;
|
||||
private string uploadId;
|
||||
|
||||
private ListPartsRequest listPartsRequest;
|
||||
|
||||
private List<UploadPartCopyRequest> uploadCopyCopyRequestList;
|
||||
private List<SliceStruct> sliceList;
|
||||
private Object syncPartCopyCount = new object();
|
||||
private int sliceCount;
|
||||
|
||||
private CompleteMultipartUploadRequest completeMultiUploadRequest;
|
||||
|
||||
private AbortMultipartUploadRequest abortMultiUploadRequest;
|
||||
|
||||
|
||||
public COSXMLCopyTask(string bucket, string region, string key, CopySourceStruct copySource)
|
||||
:base(bucket, region, key)
|
||||
{
|
||||
this.copySource = copySource;
|
||||
}
|
||||
|
||||
internal void SetDivision(long divisionSize, long sliceSize)
|
||||
{
|
||||
this.divisionSize = divisionSize;
|
||||
this.sliceSize = sliceSize;
|
||||
}
|
||||
|
||||
internal void Copy()
|
||||
{
|
||||
UpdateTaskState(TaskState.WAITTING);
|
||||
//源对象是否存在
|
||||
if (copySource == null)
|
||||
{
|
||||
lock (syncExit)
|
||||
{
|
||||
if (isExit)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (UpdateTaskState(TaskState.FAILED))
|
||||
{
|
||||
if (failCallback != null)
|
||||
{
|
||||
failCallback(new CosClientException((int)CosClientError.INVALID_ARGUMENT, "copySource = null"), null);
|
||||
}
|
||||
|
||||
}
|
||||
//error
|
||||
return;
|
||||
}
|
||||
headObjectRequest = new HeadObjectRequest(copySource.bucket, copySource.key);
|
||||
headObjectRequest.Region = copySource.region;
|
||||
cosXmlServer.HeadObject(headObjectRequest, delegate(CosResult cosResult)
|
||||
{
|
||||
lock (syncExit)
|
||||
{
|
||||
if (isExit)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (UpdateTaskState(TaskState.RUNNING))
|
||||
{
|
||||
HeadObjectResult result = cosResult as HeadObjectResult;
|
||||
//源对象的长度
|
||||
sourceSize = result.size;
|
||||
if (sourceSize > divisionSize)
|
||||
{
|
||||
MultiPartCopy();
|
||||
}
|
||||
else
|
||||
{
|
||||
SimpleCopy();
|
||||
}
|
||||
}
|
||||
|
||||
},
|
||||
delegate(CosClientException clientEx, CosServerException serverEx)
|
||||
{
|
||||
lock (syncExit)
|
||||
{
|
||||
if (isExit)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (UpdateTaskState(TaskState.FAILED))
|
||||
{
|
||||
if (failCallback != null)
|
||||
{
|
||||
failCallback(clientEx, serverEx);
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
private void SimpleCopy()
|
||||
{
|
||||
copyObjectRequest = new CopyObjectRequest(bucket, key);
|
||||
copyObjectRequest.SetCopyMetaDataDirective(Common.CosMetaDataDirective.COPY);
|
||||
copyObjectRequest.SetCopySource(copySource);
|
||||
cosXmlServer.CopyObject(copyObjectRequest, delegate(CosResult cosResult)
|
||||
{
|
||||
lock (syncExit)
|
||||
{
|
||||
if (isExit)
|
||||
{
|
||||
if (taskState == TaskState.CANCEL)
|
||||
{
|
||||
DeleteObject();
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (UpdateTaskState(TaskState.COMPLETED))
|
||||
{
|
||||
CopyObjectResult result = cosResult as CopyObjectResult;
|
||||
CopyTaskResult copyTaskResult = new CopyTaskResult();
|
||||
copyTaskResult.SetResult(result);
|
||||
if (successCallback != null)
|
||||
{
|
||||
successCallback(copyTaskResult);
|
||||
}
|
||||
}
|
||||
},
|
||||
delegate(CosClientException clientEx, CosServerException serverEx)
|
||||
{
|
||||
lock (syncExit)
|
||||
{
|
||||
if (isExit)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (UpdateTaskState(TaskState.FAILED))
|
||||
{
|
||||
if (failCallback != null)
|
||||
{
|
||||
failCallback(clientEx, serverEx);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void MultiPartCopy()
|
||||
{
|
||||
if (uploadId != null)
|
||||
{
|
||||
//list -> partCopy -> complete
|
||||
ListParts();
|
||||
}
|
||||
else
|
||||
{
|
||||
// init -> partCopy - > complete
|
||||
InitMultiUploadPart();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void InitMultiUploadPart()
|
||||
{
|
||||
initMultiUploadRequest = new InitMultipartUploadRequest(bucket, key);
|
||||
cosXmlServer.InitMultipartUpload(initMultiUploadRequest, delegate(CosResult cosResult)
|
||||
{
|
||||
lock (syncExit)
|
||||
{
|
||||
if (isExit)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
InitMultipartUploadResult result = cosResult as InitMultipartUploadResult;
|
||||
uploadId = result.initMultipartUpload.uploadId;
|
||||
//计算分片块
|
||||
ComputeSliceNums();
|
||||
//通知执行PartCopy
|
||||
OnInit();
|
||||
|
||||
},
|
||||
delegate(CosClientException clientEx, CosServerException serverEx)
|
||||
{
|
||||
lock (syncExit)
|
||||
{
|
||||
if (isExit)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (UpdateTaskState(TaskState.FAILED))
|
||||
{
|
||||
OnFailed(clientEx, serverEx);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void ListParts()
|
||||
{
|
||||
listPartsRequest = new ListPartsRequest(bucket, key, uploadId);
|
||||
cosXmlServer.ListParts(listPartsRequest, delegate (CosResult cosResult)
|
||||
{
|
||||
lock (syncExit)
|
||||
{
|
||||
if (isExit)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
ListPartsResult result = cosResult as ListPartsResult;
|
||||
//更新分块
|
||||
UpdateSliceNums(result);
|
||||
//通知执行PartCopy
|
||||
OnInit();
|
||||
|
||||
},
|
||||
delegate (CosClientException clientEx, CosServerException serverEx)
|
||||
{
|
||||
lock (syncExit)
|
||||
{
|
||||
if (isExit)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (UpdateTaskState(TaskState.FAILED))
|
||||
{
|
||||
OnFailed(clientEx, serverEx);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void PartCopy()
|
||||
{
|
||||
int size = sliceList.Count;
|
||||
sliceCount = size;
|
||||
uploadCopyCopyRequestList = new List<UploadPartCopyRequest>(size);
|
||||
for (int i = 0; i < size; i ++ )
|
||||
{
|
||||
if (isExit) return;
|
||||
SliceStruct sliceStruct = sliceList[i];
|
||||
if (!sliceStruct.isAlreadyUpload)
|
||||
{
|
||||
UploadPartCopyRequest uploadPartCopyRequest = new UploadPartCopyRequest(bucket, key, sliceStruct.partNumber, uploadId);
|
||||
uploadPartCopyRequest.SetCopySource(copySource);
|
||||
uploadPartCopyRequest.SetCopyRange(sliceStruct.sliceStart, sliceStruct.sliceEnd);
|
||||
uploadCopyCopyRequestList.Add(uploadPartCopyRequest);
|
||||
cosXmlServer.PartCopy(uploadPartCopyRequest, delegate(CosResult result)
|
||||
{
|
||||
lock (syncExit)
|
||||
{
|
||||
if (isExit)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
UploadPartCopyResult uploadPartCopyResult = result as UploadPartCopyResult;
|
||||
sliceStruct.eTag = uploadPartCopyResult.copyObject.eTag;
|
||||
lock (syncPartCopyCount)
|
||||
{
|
||||
sliceCount--;
|
||||
if (sliceCount == 0)
|
||||
{
|
||||
OnPart();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}, delegate(CosClientException clientEx, CosServerException serverEx)
|
||||
{
|
||||
lock (syncExit)
|
||||
{
|
||||
if (isExit)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (UpdateTaskState(TaskState.FAILED))
|
||||
{
|
||||
OnFailed(clientEx, serverEx);
|
||||
}
|
||||
return;
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
lock (syncPartCopyCount)
|
||||
{
|
||||
sliceCount--;
|
||||
if (sliceCount == 0)
|
||||
{
|
||||
OnPart();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void ComputeSliceNums()
|
||||
{
|
||||
int count = (int)(sourceSize / sliceSize);
|
||||
sliceList = new List<SliceStruct>(count > 0 ? count : 1);
|
||||
int i = 1; // partNumber >= 1
|
||||
for(; i < count; i++)
|
||||
{
|
||||
SliceStruct sliceStruct = new SliceStruct();
|
||||
sliceStruct.partNumber = i;
|
||||
sliceStruct.isAlreadyUpload = false;
|
||||
sliceStruct.sliceStart = (i - 1) * sliceSize;
|
||||
sliceStruct.sliceEnd = i * sliceSize - 1;
|
||||
sliceList.Add(sliceStruct);
|
||||
}
|
||||
SliceStruct lastSliceStruct = new SliceStruct();
|
||||
lastSliceStruct.partNumber = i;
|
||||
lastSliceStruct.isAlreadyUpload = false;
|
||||
lastSliceStruct.sliceStart = (i - 1) * sliceSize;
|
||||
lastSliceStruct.sliceEnd = sourceSize - 1;
|
||||
sliceList.Add(lastSliceStruct);
|
||||
}
|
||||
|
||||
private void UpdateSliceNums(ListPartsResult listPartsResult)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (listPartsResult.listParts.parts != null)
|
||||
{
|
||||
//获取原来的parts并提取partNumber
|
||||
Dictionary<int, SliceStruct> sourceParts = new Dictionary<int, SliceStruct>(sliceList.Count);
|
||||
foreach (SliceStruct sliceStruct in sliceList)
|
||||
{
|
||||
sourceParts.Add(sliceStruct.partNumber, sliceStruct);
|
||||
}
|
||||
foreach (ListParts.Part part in listPartsResult.listParts.parts)
|
||||
{
|
||||
int partNumber = -1;
|
||||
bool parse = int.TryParse(part.partNumber, out partNumber);
|
||||
if (!parse) throw new ArgumentException("ListParts.Part parse error");
|
||||
SliceStruct sliceStruct = sourceParts[partNumber];
|
||||
sliceStruct.isAlreadyUpload = true;
|
||||
sliceStruct.eTag = part.eTag;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
lock (syncExit)
|
||||
{
|
||||
if (isExit)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (UpdateTaskState(TaskState.FAILED))
|
||||
{
|
||||
OnFailed(new CosClientException((int)CosClientError.INTERNA_LERROR, ex.Message, ex), null);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
private void CompleteMultipartUpload()
|
||||
{
|
||||
completeMultiUploadRequest = new CompleteMultipartUploadRequest(bucket, key, uploadId);
|
||||
foreach (SliceStruct sliceStruct in sliceList)
|
||||
{
|
||||
completeMultiUploadRequest.SetPartNumberAndETag(sliceStruct.partNumber, sliceStruct.eTag); // partNumberEtag 有序的
|
||||
}
|
||||
cosXmlServer.CompleteMultiUpload(completeMultiUploadRequest, delegate(CosResult result)
|
||||
{
|
||||
lock (syncExit)
|
||||
{
|
||||
if (isExit)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (UpdateTaskState(TaskState.COMPLETED))
|
||||
{
|
||||
CompleteMultipartUploadResult completeMultiUploadResult = result as CompleteMultipartUploadResult;
|
||||
OnCompleted(completeMultiUploadResult);
|
||||
}
|
||||
}, delegate(CosClientException clientEx, CosServerException serverEx)
|
||||
{
|
||||
lock (syncExit)
|
||||
{
|
||||
if (isExit)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (UpdateTaskState(TaskState.FAILED))
|
||||
{
|
||||
OnFailed(clientEx, serverEx);
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
public void OnInit()
|
||||
{
|
||||
//获取了uploadId
|
||||
PartCopy();
|
||||
}
|
||||
|
||||
public void OnPart()
|
||||
{
|
||||
//获取了 part ETag
|
||||
CompleteMultipartUpload();
|
||||
|
||||
}
|
||||
|
||||
public void OnCompleted(CompleteMultipartUploadResult result)
|
||||
{
|
||||
uploadId = null;
|
||||
//lock (syncExit)
|
||||
//{
|
||||
// isExit = true;
|
||||
//}
|
||||
//success
|
||||
if (successCallback != null)
|
||||
{
|
||||
CopyTaskResult copyTaskResult = new CopyTaskResult();
|
||||
copyTaskResult.SetResult(result);
|
||||
successCallback(copyTaskResult);
|
||||
}
|
||||
}
|
||||
|
||||
public void OnFailed(CosClientException clientEx, CosServerException serverEx)
|
||||
{
|
||||
if (!isExit)
|
||||
{
|
||||
lock (syncExit)
|
||||
{
|
||||
isExit = true;
|
||||
}
|
||||
}
|
||||
if (failCallback != null)
|
||||
{
|
||||
failCallback(clientEx, serverEx);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void Abort()
|
||||
{
|
||||
abortMultiUploadRequest = new AbortMultipartUploadRequest(bucket, key, uploadId);
|
||||
cosXmlServer.AbortMultiUpload(abortMultiUploadRequest, delegate (CosResult cosResult) { },
|
||||
delegate (CosClientException cosClientException, CosServerException cosServerException) { DeleteObject(); });
|
||||
}
|
||||
|
||||
private void DeleteObject()
|
||||
{
|
||||
deleteObjectRequest = new DeleteObjectRequest(bucket, key);
|
||||
cosXmlServer.DeleteObject(deleteObjectRequest, delegate (CosResult cosResult) { },
|
||||
delegate (CosClientException cosClientException, CosServerException cosServerException) { });
|
||||
}
|
||||
|
||||
private void RealCancle()
|
||||
{
|
||||
//cancle request
|
||||
cosXmlServer.Cancel(headObjectRequest);
|
||||
cosXmlServer.Cancel(copyObjectRequest);
|
||||
cosXmlServer.Cancel(initMultiUploadRequest);
|
||||
cosXmlServer.Cancel(completeMultiUploadRequest);
|
||||
if (uploadCopyCopyRequestList != null)
|
||||
{
|
||||
foreach (UploadPartCopyRequest uploadPartCopyRequest in uploadCopyCopyRequestList)
|
||||
{
|
||||
cosXmlServer.Cancel(uploadPartCopyRequest);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void Pause()
|
||||
{
|
||||
if (UpdateTaskState(TaskState.PAUSE))
|
||||
{
|
||||
lock (syncExit) { isExit = true; }//exit copy
|
||||
//cancle request
|
||||
RealCancle();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public override void Cancel()
|
||||
{
|
||||
if (UpdateTaskState(TaskState.CANCEL))
|
||||
{
|
||||
lock (syncExit) { isExit = true; }//exit copy
|
||||
//cancle request
|
||||
RealCancle();
|
||||
//abort
|
||||
Abort();
|
||||
uploadId = null;
|
||||
}
|
||||
}
|
||||
|
||||
public override void Resume()
|
||||
{
|
||||
if (UpdateTaskState(TaskState.RESUME))
|
||||
{
|
||||
lock (syncExit)
|
||||
{
|
||||
isExit = false;//continue to copy
|
||||
}
|
||||
Copy();
|
||||
}
|
||||
}
|
||||
|
||||
public class CopyTaskResult : CosResult
|
||||
{
|
||||
public string eTag;
|
||||
|
||||
public void SetResult(CopyObjectResult result)
|
||||
{
|
||||
this.eTag = result.copyObject.eTag;
|
||||
this.httpCode = result.httpCode;
|
||||
this.httpMessage = result.httpMessage;
|
||||
this.responseHeaders = result.responseHeaders;
|
||||
}
|
||||
|
||||
public void SetResult(CompleteMultipartUploadResult result)
|
||||
{
|
||||
this.eTag = result.completeResult.eTag;
|
||||
this.httpCode = result.httpCode;
|
||||
this.httpMessage = result.httpMessage;
|
||||
this.responseHeaders = result.responseHeaders;
|
||||
}
|
||||
|
||||
public override string GetResultInfo()
|
||||
{
|
||||
return base.GetResultInfo() + ("\n : ETag: " + eTag);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
205
COSXML/Transfer/COSXMLDownloadTask.cs
Normal file
205
COSXML/Transfer/COSXMLDownloadTask.cs
Normal file
@@ -0,0 +1,205 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using COSXML.Model.Object;
|
||||
using COSXML.Utils;
|
||||
using COSXML.Model;
|
||||
using COSXML.CosException;
|
||||
/**
|
||||
* Copyright (c) 2018 Tencent Cloud. All rights reserved.
|
||||
* 11/29/2018 4:58:58 PM
|
||||
* bradyxiao
|
||||
*/
|
||||
namespace COSXML.Transfer
|
||||
{
|
||||
public sealed class COSXMLDownloadTask : COSXMLTask
|
||||
{
|
||||
private string localDir;
|
||||
private string localFileName;
|
||||
private long localFileOffset;
|
||||
|
||||
private long rangeStart = -1L;
|
||||
private long rangeEnd = -1L;
|
||||
|
||||
private HeadObjectRequest headObjectRequest;
|
||||
|
||||
private GetObjectRequest getObjectRequest;
|
||||
|
||||
private Object syncExit = new Object();
|
||||
private bool isExit = false;
|
||||
|
||||
public COSXMLDownloadTask(string bucket, string region, string key, string localDir, string localFileName)
|
||||
: base(bucket, region, key)
|
||||
{
|
||||
this.localDir = localDir;
|
||||
this.localFileName = localFileName;
|
||||
}
|
||||
|
||||
public void SetRange(long rangeStart, long rangeEnd)
|
||||
{
|
||||
this.rangeStart = rangeStart;
|
||||
this.rangeEnd = rangeEnd;
|
||||
}
|
||||
|
||||
public void SetLocalFileOffset(long localFileOffset)
|
||||
{
|
||||
this.localFileOffset = localFileOffset;
|
||||
}
|
||||
|
||||
internal void Download()
|
||||
{
|
||||
UpdateTaskState(TaskState.WAITTING);
|
||||
//对象是否存在
|
||||
headObjectRequest = new HeadObjectRequest(bucket, key);
|
||||
cosXmlServer.HeadObject(headObjectRequest, delegate(CosResult cosResult)
|
||||
{
|
||||
lock (syncExit)
|
||||
{
|
||||
if (isExit)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (UpdateTaskState(TaskState.RUNNING))
|
||||
{
|
||||
HeadObjectResult result = cosResult as HeadObjectResult;
|
||||
//计算range
|
||||
|
||||
//download
|
||||
GetObject();
|
||||
}
|
||||
|
||||
},
|
||||
delegate(CosClientException clientEx, CosServerException serverEx)
|
||||
{
|
||||
lock (syncExit)
|
||||
{
|
||||
if (isExit)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (UpdateTaskState(TaskState.FAILED))
|
||||
{
|
||||
if (failCallback != null)
|
||||
{
|
||||
failCallback(clientEx, serverEx);
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
private void GetObject()
|
||||
{
|
||||
getObjectRequest = new GetObjectRequest(bucket, key, localDir, localFileName);
|
||||
if (progressCallback != null)
|
||||
{
|
||||
getObjectRequest.SetCosProgressCallback(progressCallback);
|
||||
}
|
||||
getObjectRequest.SetRange(rangeStart, rangeEnd);
|
||||
getObjectRequest.SetLocalFileOffset(localFileOffset);
|
||||
cosXmlServer.GetObject(getObjectRequest, delegate(CosResult result)
|
||||
{
|
||||
lock (syncExit)
|
||||
{
|
||||
if (isExit)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (UpdateTaskState(TaskState.COMPLETED))
|
||||
{
|
||||
GetObjectResult getObjectResult = result as GetObjectResult;
|
||||
DownloadTaskResult downloadTaskResult = new DownloadTaskResult();
|
||||
downloadTaskResult.SetResult(getObjectResult);
|
||||
|
||||
if (successCallback != null)
|
||||
{
|
||||
successCallback(downloadTaskResult);
|
||||
}
|
||||
}
|
||||
}, delegate(CosClientException clientEx, CosServerException serverEx)
|
||||
{
|
||||
lock (syncExit)
|
||||
{
|
||||
if (isExit)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (UpdateTaskState(TaskState.FAILED))
|
||||
{
|
||||
if (failCallback != null)
|
||||
{
|
||||
failCallback(clientEx, serverEx);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void RealCancle()
|
||||
{
|
||||
//cancle request
|
||||
cosXmlServer.Cancel(headObjectRequest);
|
||||
cosXmlServer.Cancel(getObjectRequest);
|
||||
}
|
||||
|
||||
private void Clear()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public override void Pause()
|
||||
{
|
||||
if (UpdateTaskState(TaskState.PAUSE))
|
||||
{
|
||||
lock (syncExit) { isExit = true; }//exit download
|
||||
//cancle request
|
||||
RealCancle();
|
||||
}
|
||||
}
|
||||
|
||||
public override void Cancel()
|
||||
{
|
||||
if (UpdateTaskState(TaskState.CANCEL))
|
||||
{
|
||||
lock (syncExit) { isExit = true; }//exit copy
|
||||
//cancle request
|
||||
RealCancle();
|
||||
//clear recoder
|
||||
Clear();
|
||||
}
|
||||
}
|
||||
|
||||
public override void Resume()
|
||||
{
|
||||
if (UpdateTaskState(TaskState.RESUME))
|
||||
{
|
||||
lock (syncExit)
|
||||
{
|
||||
isExit = false;//continue to download
|
||||
}
|
||||
Download();
|
||||
}
|
||||
}
|
||||
|
||||
public class DownloadTaskResult : CosResult
|
||||
{
|
||||
public string eTag;
|
||||
|
||||
public void SetResult(GetObjectResult result)
|
||||
{
|
||||
this.eTag = result.eTag;
|
||||
this.httpCode = result.httpCode;
|
||||
this.httpMessage = result.httpMessage;
|
||||
this.responseHeaders = result.responseHeaders;
|
||||
}
|
||||
|
||||
public override string GetResultInfo()
|
||||
{
|
||||
return base.GetResultInfo() + ("\n : ETag: " + eTag);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
159
COSXML/Transfer/COSXMLTask.cs
Normal file
159
COSXML/Transfer/COSXMLTask.cs
Normal file
@@ -0,0 +1,159 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using COSXML.Model;
|
||||
using COSXML.Model.Object;
|
||||
using COSXML.CosException;
|
||||
/**
|
||||
* Copyright (c) 2018 Tencent Cloud. All rights reserved.
|
||||
* 11/29/2018 5:08:32 PM
|
||||
* bradyxiao
|
||||
*/
|
||||
namespace COSXML.Transfer
|
||||
{
|
||||
public abstract class COSXMLTask
|
||||
{
|
||||
public COSXML.Callback.OnProgressCallback progressCallback;
|
||||
|
||||
public COSXML.Callback.OnSuccessCallback<CosResult> successCallback;
|
||||
|
||||
public COSXML.Callback.OnFailedCallback failCallback;
|
||||
|
||||
public OnInternalHandleBeforExcute onInternalHandle;
|
||||
|
||||
public OnState onState;
|
||||
|
||||
protected CosXml cosXmlServer;
|
||||
|
||||
protected string bucket;
|
||||
|
||||
protected string region;
|
||||
|
||||
protected string key;
|
||||
|
||||
protected bool isNeedMd5 = true;
|
||||
|
||||
protected TaskState taskState;
|
||||
protected Object syncTaskState = new Object();
|
||||
|
||||
public void InitCosXmlServer(CosXml cosXml)
|
||||
{
|
||||
cosXmlServer = cosXml;
|
||||
}
|
||||
|
||||
|
||||
public COSXMLTask(string bucket, string region, string key)
|
||||
{
|
||||
this.bucket = bucket;
|
||||
this.region = region;
|
||||
this.key = key;
|
||||
}
|
||||
|
||||
public abstract void Pause();
|
||||
|
||||
public abstract void Cancel();
|
||||
|
||||
public abstract void Resume();
|
||||
|
||||
protected bool UpdateTaskState(TaskState newTaskState)
|
||||
{
|
||||
bool result = false;
|
||||
lock (syncTaskState)
|
||||
{
|
||||
switch (newTaskState)
|
||||
{
|
||||
case TaskState.WAITTING:
|
||||
taskState = newTaskState;
|
||||
if (onState != null) onState(taskState);
|
||||
result = true;
|
||||
break;
|
||||
case TaskState.RUNNING:
|
||||
if (taskState == TaskState.WAITTING)
|
||||
{
|
||||
taskState = newTaskState;
|
||||
if (onState != null) onState(taskState);
|
||||
result = true;
|
||||
}
|
||||
break;
|
||||
case TaskState.COMPLETED:
|
||||
if (taskState == TaskState.RUNNING)
|
||||
{
|
||||
taskState = newTaskState;
|
||||
if (onState != null) onState(taskState);
|
||||
result = true;
|
||||
}
|
||||
break;
|
||||
case TaskState.FAILED:
|
||||
if (taskState == TaskState.WAITTING || taskState == TaskState.RUNNING)
|
||||
{
|
||||
taskState = newTaskState;
|
||||
if (onState != null) onState(taskState);
|
||||
result = true;
|
||||
}
|
||||
break;
|
||||
case TaskState.PAUSE:
|
||||
if (taskState == TaskState.WAITTING || taskState == TaskState.RUNNING)
|
||||
{
|
||||
taskState = newTaskState;
|
||||
if (onState != null) onState(taskState);
|
||||
result = true;
|
||||
}
|
||||
break;
|
||||
case TaskState.CANCEL:
|
||||
if (taskState != TaskState.COMPLETED || taskState != TaskState.CANCEL)
|
||||
{
|
||||
taskState = newTaskState;
|
||||
if (onState != null) onState(taskState);
|
||||
result = true;
|
||||
}
|
||||
break;
|
||||
case TaskState.RESUME:
|
||||
if (taskState == TaskState.PAUSE || taskState == TaskState.FAILED)
|
||||
{
|
||||
taskState = newTaskState;
|
||||
if (onState != null) onState(taskState);
|
||||
result = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
internal class SliceStruct
|
||||
{
|
||||
public int partNumber;
|
||||
public bool isAlreadyUpload;
|
||||
public long sliceStart;
|
||||
public long sliceEnd;
|
||||
public long sliceLength;
|
||||
public string eTag;
|
||||
}
|
||||
|
||||
public enum TaskState
|
||||
{
|
||||
WAITTING = 0,
|
||||
RUNNING,
|
||||
COMPLETED,
|
||||
FAILED,
|
||||
CANCEL,
|
||||
PAUSE,
|
||||
RESUME,
|
||||
}
|
||||
|
||||
public delegate void OnState(TaskState taskState);
|
||||
|
||||
public delegate void OnInternalHandleBeforExcute(CosRequest cosRequest);
|
||||
|
||||
internal interface OnMultipartUploadStateListener
|
||||
{
|
||||
void OnInit();
|
||||
void OnPart();
|
||||
void OnCompleted(CompleteMultipartUploadResult result);
|
||||
void OnFailed(CosClientException clientEx, CosServerException serverEx);
|
||||
}
|
||||
|
||||
}
|
||||
630
COSXML/Transfer/COSXMLUploadTask.cs
Normal file
630
COSXML/Transfer/COSXMLUploadTask.cs
Normal file
@@ -0,0 +1,630 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using COSXML.Model;
|
||||
using COSXML.CosException;
|
||||
using COSXML.Model.Object;
|
||||
using System.IO;
|
||||
using COSXML.Common;
|
||||
using COSXML.Utils;
|
||||
using COSXML.Model.Tag;
|
||||
using COSXML.Log;
|
||||
using System.Threading;
|
||||
/**
|
||||
* Copyright (c) 2018 Tencent Cloud. All rights reserved.
|
||||
* 11/29/2018 4:58:32 PM
|
||||
* bradyxiao
|
||||
*/
|
||||
namespace COSXML.Transfer
|
||||
{
|
||||
public sealed class COSXMLUploadTask : COSXMLTask, OnMultipartUploadStateListener
|
||||
{
|
||||
private long divisionSize;
|
||||
private long sliceSize;
|
||||
|
||||
private const int MAX_ACTIVIE_TASKS = 2;
|
||||
private volatile int activieTasks = 0;
|
||||
|
||||
private long sendOffset = 0L;
|
||||
private long sendContentLength = -1L; // 实际要发送的总长度,类似于content-length
|
||||
private string srcPath;
|
||||
|
||||
private PutObjectRequest putObjectRequest;
|
||||
private DeleteObjectRequest deleteObjectRequest;
|
||||
|
||||
private Object syncExit = new Object();
|
||||
private bool isExit = false;
|
||||
|
||||
private ListPartsRequest listPartsRequest;
|
||||
|
||||
private InitMultipartUploadRequest initMultiUploadRequest;
|
||||
private string uploadId;
|
||||
|
||||
private Dictionary<UploadPartRequest, long> uploadPartRequestMap;
|
||||
private List<UploadPartRequest> uploadPartRequestList;
|
||||
private List<SliceStruct> sliceList;
|
||||
private Object syncPartCopyCount = new object();
|
||||
private int sliceCount;
|
||||
private long hasReceiveDataLength = 0;
|
||||
private object syncProgress = new Object();
|
||||
|
||||
private CompleteMultipartUploadRequest completeMultiUploadRequest;
|
||||
|
||||
private AbortMultipartUploadRequest abortMultiUploadRequest;
|
||||
|
||||
public COSXMLUploadTask(string bucket, string region, string key)
|
||||
: base(bucket, region, key)
|
||||
{
|
||||
}
|
||||
|
||||
internal void SetDivision(long divisionSize, long sliceSize)
|
||||
{
|
||||
this.divisionSize = divisionSize;
|
||||
this.sliceSize = sliceSize;
|
||||
}
|
||||
|
||||
public void SetSrcPath(string srcPath)
|
||||
{
|
||||
SetSrcPath(srcPath, -1L, -1L);
|
||||
}
|
||||
|
||||
public void SetSrcPath(string srcPath, long fileOffset, long contentLength)
|
||||
{
|
||||
this.srcPath = srcPath;
|
||||
this.sendOffset = fileOffset >= 0 ? fileOffset : 0;
|
||||
this.sendContentLength = contentLength >= 0 ? contentLength : -1L;
|
||||
}
|
||||
|
||||
public void SetUploadId(string uploadId)
|
||||
{
|
||||
this.uploadId = uploadId;
|
||||
}
|
||||
|
||||
internal void Upload()
|
||||
{
|
||||
//UpdateTaskState(TaskState.WAITTING);
|
||||
taskState = TaskState.WAITTING;
|
||||
hasReceiveDataLength = 0;
|
||||
FileInfo fileInfo = null;
|
||||
long sourceLength = 0;
|
||||
try
|
||||
{
|
||||
fileInfo = new FileInfo(srcPath);
|
||||
sourceLength = fileInfo.Length;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
lock (syncExit)
|
||||
{
|
||||
if (isExit)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (UpdateTaskState(TaskState.FAILED))
|
||||
{
|
||||
if (failCallback != null)
|
||||
{
|
||||
failCallback(new CosClientException((int)CosClientError.INVALID_ARGUMENT, ex.Message, ex), null);
|
||||
}
|
||||
}
|
||||
//error
|
||||
return;
|
||||
}
|
||||
|
||||
if(sendContentLength == -1L || (sendContentLength + sendOffset > sourceLength))
|
||||
{
|
||||
sendContentLength = sourceLength - sendOffset;
|
||||
}
|
||||
taskState = TaskState.RUNNING;
|
||||
if (sendContentLength > divisionSize)
|
||||
{
|
||||
MultiUpload();
|
||||
}
|
||||
else
|
||||
{
|
||||
SimpleUpload();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void SimpleUpload()
|
||||
{
|
||||
putObjectRequest = new PutObjectRequest(bucket, key, srcPath, sendOffset, sendContentLength);
|
||||
if (progressCallback != null)
|
||||
{
|
||||
putObjectRequest.SetCosProgressCallback(progressCallback);
|
||||
}
|
||||
cosXmlServer.PutObject(putObjectRequest, delegate(CosResult cosResult)
|
||||
{
|
||||
lock (syncExit)
|
||||
{
|
||||
if (isExit)
|
||||
{
|
||||
if (taskState == TaskState.CANCEL)
|
||||
{
|
||||
DeleteObject();
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (UpdateTaskState(TaskState.COMPLETED))
|
||||
{
|
||||
PutObjectResult result = cosResult as PutObjectResult;
|
||||
UploadTaskResult copyTaskResult = new UploadTaskResult();
|
||||
copyTaskResult.SetResult(result);
|
||||
if (successCallback != null)
|
||||
{
|
||||
successCallback(copyTaskResult);
|
||||
}
|
||||
}
|
||||
|
||||
},
|
||||
delegate(CosClientException clientEx, CosServerException serverEx)
|
||||
{
|
||||
lock (syncExit)
|
||||
{
|
||||
if (isExit)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (UpdateTaskState(TaskState.FAILED))
|
||||
{
|
||||
if (failCallback != null)
|
||||
{
|
||||
failCallback(clientEx, serverEx);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void MultiUpload()
|
||||
{
|
||||
ComputeSliceNums();
|
||||
if (uploadId != null)
|
||||
{
|
||||
ListMultiParts();
|
||||
}
|
||||
else
|
||||
{
|
||||
InitMultiUploadPart();
|
||||
}
|
||||
}
|
||||
|
||||
private void InitMultiUploadPart()
|
||||
{
|
||||
initMultiUploadRequest = new InitMultipartUploadRequest(bucket, key);
|
||||
cosXmlServer.InitMultipartUpload(initMultiUploadRequest, delegate(CosResult cosResult)
|
||||
{
|
||||
lock (syncExit)
|
||||
{
|
||||
if (isExit)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
InitMultipartUploadResult result = cosResult as InitMultipartUploadResult;
|
||||
uploadId = result.initMultipartUpload.uploadId;
|
||||
//通知执行PartCopy
|
||||
OnInit();
|
||||
|
||||
},
|
||||
delegate(CosClientException clientEx, CosServerException serverEx)
|
||||
{
|
||||
lock (syncExit)
|
||||
{
|
||||
if (isExit)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (UpdateTaskState(TaskState.FAILED))
|
||||
{
|
||||
OnFailed(clientEx, serverEx);
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
private void ListMultiParts()
|
||||
{
|
||||
listPartsRequest = new ListPartsRequest(bucket, key, uploadId);
|
||||
cosXmlServer.ListParts(listPartsRequest, delegate(CosResult cosResult)
|
||||
{
|
||||
lock (syncExit)
|
||||
{
|
||||
if (isExit)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
ListPartsResult result = cosResult as ListPartsResult;
|
||||
//更细listParts
|
||||
UpdateSliceNums(result);
|
||||
//通知执行PartCopy
|
||||
OnInit();
|
||||
|
||||
},
|
||||
delegate(CosClientException clientEx, CosServerException serverEx)
|
||||
{
|
||||
lock (syncExit)
|
||||
{
|
||||
if (isExit)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (UpdateTaskState(TaskState.FAILED))
|
||||
{
|
||||
OnFailed(clientEx, serverEx);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void UploadPart()
|
||||
{
|
||||
activieTasks = 0;
|
||||
int size = sliceList.Count;
|
||||
sliceCount = size;
|
||||
uploadPartRequestMap = new Dictionary<UploadPartRequest, long>(size);
|
||||
uploadPartRequestList = new List<UploadPartRequest>(size);
|
||||
|
||||
AutoResetEvent resetEvent = new AutoResetEvent(false);
|
||||
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
if (activieTasks > MAX_ACTIVIE_TASKS)
|
||||
{
|
||||
resetEvent.WaitOne();
|
||||
}
|
||||
lock (syncExit)
|
||||
{
|
||||
if (isExit)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
SliceStruct sliceStruct = sliceList[i];
|
||||
if (!sliceStruct.isAlreadyUpload)
|
||||
{
|
||||
UploadPartRequest uploadPartRequest = new UploadPartRequest(bucket, key, sliceStruct.partNumber, uploadId, srcPath, sliceStruct.sliceStart,
|
||||
sliceStruct.sliceLength);
|
||||
|
||||
//打印进度
|
||||
uploadPartRequest.SetCosProgressCallback(delegate (long completed, long total)
|
||||
{
|
||||
lock (syncProgress)
|
||||
{
|
||||
long dataLen = hasReceiveDataLength + completed - uploadPartRequestMap[uploadPartRequest];
|
||||
UpdateProgress(dataLen, sendContentLength, false);
|
||||
hasReceiveDataLength = dataLen;
|
||||
uploadPartRequestMap[uploadPartRequest] = completed;
|
||||
}
|
||||
});
|
||||
|
||||
uploadPartRequestMap.Add(uploadPartRequest, 0);
|
||||
uploadPartRequestList.Add(uploadPartRequest);
|
||||
|
||||
|
||||
Interlocked.Increment(ref activieTasks);
|
||||
|
||||
cosXmlServer.UploadPart(uploadPartRequest, delegate (CosResult result)
|
||||
{
|
||||
Interlocked.Decrement(ref activieTasks);
|
||||
UploadPartResult uploadPartResult = result as UploadPartResult;
|
||||
sliceStruct.eTag = uploadPartResult.eTag;
|
||||
lock (syncPartCopyCount)
|
||||
{
|
||||
sliceCount--;
|
||||
if (sliceCount == 0)
|
||||
{
|
||||
OnPart();
|
||||
}
|
||||
}
|
||||
resetEvent.Set();
|
||||
|
||||
}, delegate (CosClientException clientEx, CosServerException serverEx)
|
||||
{
|
||||
Interlocked.Decrement(ref activieTasks);
|
||||
if (UpdateTaskState(TaskState.FAILED))
|
||||
{
|
||||
OnFailed(clientEx, serverEx);
|
||||
}
|
||||
resetEvent.Set();
|
||||
});
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
lock (syncPartCopyCount)
|
||||
{
|
||||
sliceCount--;
|
||||
if (sliceCount == 0)
|
||||
{
|
||||
OnPart();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateProgress(long complete, long total, bool isCompleted)
|
||||
{
|
||||
|
||||
lock (syncExit)
|
||||
{
|
||||
if (isExit)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (complete < total)
|
||||
{
|
||||
if (progressCallback != null)
|
||||
{
|
||||
progressCallback(complete, total);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (isCompleted)
|
||||
{
|
||||
if (progressCallback != null)
|
||||
{
|
||||
progressCallback(complete, total);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (progressCallback != null)
|
||||
{
|
||||
progressCallback(total - 1, total);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void CompleteMultipartUpload()
|
||||
{
|
||||
completeMultiUploadRequest = new CompleteMultipartUploadRequest(bucket, key, uploadId);
|
||||
foreach (SliceStruct sliceStruct in sliceList)
|
||||
{
|
||||
completeMultiUploadRequest.SetPartNumberAndETag(sliceStruct.partNumber, sliceStruct.eTag); // partNumberEtag 有序的
|
||||
}
|
||||
cosXmlServer.CompleteMultiUpload(completeMultiUploadRequest, delegate(CosResult result)
|
||||
{
|
||||
lock (syncExit)
|
||||
{
|
||||
if (isExit)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (UpdateTaskState(TaskState.COMPLETED))
|
||||
{
|
||||
CompleteMultipartUploadResult completeMultiUploadResult = result as CompleteMultipartUploadResult;
|
||||
OnCompleted(completeMultiUploadResult);
|
||||
}
|
||||
|
||||
}, delegate(CosClientException clientEx, CosServerException serverEx)
|
||||
{
|
||||
lock (syncExit)
|
||||
{
|
||||
if (isExit)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (UpdateTaskState(TaskState.FAILED))
|
||||
{
|
||||
OnFailed(clientEx, serverEx);
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
private void ComputeSliceNums()
|
||||
{
|
||||
int count = (int)(sendContentLength / sliceSize);
|
||||
sliceList = new List<SliceStruct>(count > 0 ? count : 1);
|
||||
int i = 1;// partNumber >= 1
|
||||
for (; i < count; i++)
|
||||
{
|
||||
SliceStruct sliceStruct = new SliceStruct();
|
||||
sliceStruct.partNumber = i;
|
||||
sliceStruct.isAlreadyUpload = false;
|
||||
sliceStruct.sliceStart = sendOffset + (i - 1) * sliceSize;
|
||||
sliceStruct.sliceLength = sliceSize;
|
||||
sliceStruct.sliceEnd = sendOffset + i * sliceSize - 1;
|
||||
sliceList.Add(sliceStruct);
|
||||
}
|
||||
SliceStruct lastSliceStruct = new SliceStruct();
|
||||
lastSliceStruct.partNumber = i;
|
||||
lastSliceStruct.isAlreadyUpload = false;
|
||||
lastSliceStruct.sliceStart = sendOffset + (i - 1) * sliceSize;
|
||||
lastSliceStruct.sliceLength = sendContentLength - (i - 1) * sliceSize;
|
||||
lastSliceStruct.sliceEnd = sendOffset + sendContentLength - 1;
|
||||
sliceList.Add(lastSliceStruct);
|
||||
}
|
||||
|
||||
private void UpdateSliceNums(ListPartsResult listPartsResult)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (listPartsResult.listParts.parts != null)
|
||||
{
|
||||
//获取原来的parts并提取partNumber
|
||||
Dictionary<int, SliceStruct> sourceParts = new Dictionary<int, SliceStruct>(sliceList.Count);
|
||||
foreach (SliceStruct sliceStruct in sliceList)
|
||||
{
|
||||
sourceParts.Add(sliceStruct.partNumber, sliceStruct);
|
||||
}
|
||||
foreach (ListParts.Part part in listPartsResult.listParts.parts)
|
||||
{
|
||||
int partNumber = -1;
|
||||
bool parse = int.TryParse(part.partNumber, out partNumber);
|
||||
if (!parse) throw new ArgumentException("ListParts.Part parse error");
|
||||
SliceStruct sliceStruct = sourceParts[partNumber];
|
||||
sliceStruct.isAlreadyUpload = true;
|
||||
sliceStruct.eTag = part.eTag;
|
||||
lock (syncProgress)
|
||||
{
|
||||
long size = 0L;
|
||||
long.TryParse(part.size, out size);
|
||||
hasReceiveDataLength += size;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
lock (syncExit)
|
||||
{
|
||||
if (isExit)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (UpdateTaskState(TaskState.FAILED))
|
||||
{
|
||||
OnFailed(new CosClientException((int)CosClientError.INTERNA_LERROR, ex.Message, ex), null);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void OnInit()
|
||||
{
|
||||
//获取了uploadId
|
||||
UploadPart();
|
||||
}
|
||||
|
||||
public void OnPart()
|
||||
{
|
||||
//获取了 part ETag
|
||||
CompleteMultipartUpload();
|
||||
}
|
||||
|
||||
public void OnCompleted(CompleteMultipartUploadResult result)
|
||||
{
|
||||
UpdateProgress(sendContentLength, sendContentLength, true);
|
||||
//lock (syncExit)
|
||||
//{
|
||||
// isExit = true;
|
||||
//}
|
||||
if (successCallback != null)
|
||||
{
|
||||
UploadTaskResult uploadTaskResult = new UploadTaskResult();
|
||||
uploadTaskResult.SetResult(result);
|
||||
successCallback(uploadTaskResult);
|
||||
}
|
||||
}
|
||||
|
||||
public void OnFailed(CosClientException clientEx, CosServerException serverEx)
|
||||
{
|
||||
lock (syncExit)
|
||||
{
|
||||
isExit = true;
|
||||
}
|
||||
if (failCallback != null)
|
||||
{
|
||||
failCallback(clientEx, serverEx);
|
||||
}
|
||||
}
|
||||
|
||||
private void Abort()
|
||||
{
|
||||
abortMultiUploadRequest = new AbortMultipartUploadRequest(bucket, key, uploadId);
|
||||
cosXmlServer.AbortMultiUpload(abortMultiUploadRequest, delegate (CosResult cosResult) { },
|
||||
delegate (CosClientException cosClientException, CosServerException cosServerException) { DeleteObject(); });
|
||||
|
||||
}
|
||||
private void DeleteObject()
|
||||
{
|
||||
deleteObjectRequest = new DeleteObjectRequest(bucket, key);
|
||||
cosXmlServer.DeleteObject(deleteObjectRequest, delegate (CosResult cosResult) { },
|
||||
delegate (CosClientException cosClientException, CosServerException cosServerException) { });
|
||||
}
|
||||
|
||||
private void RealCancle()
|
||||
{
|
||||
//cancle request
|
||||
cosXmlServer.Cancel(putObjectRequest);
|
||||
cosXmlServer.Cancel(initMultiUploadRequest);
|
||||
cosXmlServer.Cancel(completeMultiUploadRequest);
|
||||
cosXmlServer.Cancel(listPartsRequest);
|
||||
if (uploadPartRequestList != null)
|
||||
{
|
||||
foreach (UploadPartRequest uploadPartRequest in uploadPartRequestList)
|
||||
{
|
||||
cosXmlServer.Cancel(uploadPartRequest);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void Pause()
|
||||
{
|
||||
if (UpdateTaskState(TaskState.PAUSE))
|
||||
{
|
||||
lock (syncExit) { isExit = true; }//exit upload
|
||||
//cancle request
|
||||
RealCancle();
|
||||
}
|
||||
}
|
||||
|
||||
public override void Cancel()
|
||||
{
|
||||
if (UpdateTaskState(TaskState.CANCEL))
|
||||
{
|
||||
lock (syncExit) { isExit = true; }//exit upload
|
||||
//cancle request
|
||||
RealCancle();
|
||||
//abort
|
||||
Abort();
|
||||
uploadId = null;
|
||||
}
|
||||
}
|
||||
|
||||
public override void Resume()
|
||||
{
|
||||
if (UpdateTaskState(TaskState.RESUME))
|
||||
{
|
||||
lock (syncExit)
|
||||
{
|
||||
isExit = false;//continue to upload
|
||||
}
|
||||
Upload();
|
||||
}
|
||||
}
|
||||
|
||||
public class UploadTaskResult : CosResult
|
||||
{
|
||||
public string eTag;
|
||||
|
||||
public void SetResult(PutObjectResult result)
|
||||
{
|
||||
this.eTag = result.eTag;
|
||||
this.httpCode = result.httpCode;
|
||||
this.httpMessage = result.httpMessage;
|
||||
this.responseHeaders = result.responseHeaders;
|
||||
}
|
||||
|
||||
public void SetResult(CompleteMultipartUploadResult result)
|
||||
{
|
||||
this.eTag = result.completeResult.eTag;
|
||||
this.httpCode = result.httpCode;
|
||||
this.httpMessage = result.httpMessage;
|
||||
this.responseHeaders = result.responseHeaders;
|
||||
}
|
||||
|
||||
public override string GetResultInfo()
|
||||
{
|
||||
return base.GetResultInfo() + ("\n : ETag: " + eTag);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
66
COSXML/Transfer/TransferManager.cs
Normal file
66
COSXML/Transfer/TransferManager.cs
Normal file
@@ -0,0 +1,66 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
/**
|
||||
* Copyright (c) 2018 Tencent Cloud. All rights reserved.
|
||||
* 11/29/2018 5:09:07 PM
|
||||
* bradyxiao
|
||||
*/
|
||||
namespace COSXML.Transfer
|
||||
{
|
||||
public sealed class TransferConfig
|
||||
{
|
||||
internal long divisionForCopy = 5242880; // 5M
|
||||
|
||||
internal long sliceSizeForCopy = 2097152; // 2M
|
||||
|
||||
internal long divisionForUpload = 5242880; // 5M
|
||||
|
||||
internal long sliceSizeForUpload = 1048576; // 1M
|
||||
|
||||
|
||||
public long DdivisionForCopy { get { return divisionForCopy; } set { divisionForCopy = value; } }
|
||||
|
||||
public long DivisionForUpload { get { return divisionForUpload; } set { divisionForUpload = value; } }
|
||||
|
||||
public long SliceSizeForCopy { get { return sliceSizeForCopy; } set { sliceSizeForCopy = value; } }
|
||||
|
||||
public long SliceSizeForUpload { get { return sliceSizeForUpload; } set { sliceSizeForUpload = value; } }
|
||||
}
|
||||
|
||||
public sealed class TransferManager
|
||||
{
|
||||
private TransferConfig transferConfig;
|
||||
private CosXml cosXml;
|
||||
|
||||
public TransferManager(CosXml cosXmlServer, TransferConfig transferConfig)
|
||||
{
|
||||
if (cosXmlServer == null) throw new ArgumentNullException("CosXmlServer = null");
|
||||
if (transferConfig == null) throw new ArgumentNullException("TransferConfig = null");
|
||||
this.transferConfig = transferConfig;
|
||||
//COSXMLTask.InitCosXmlServer(cosXmlServer);
|
||||
this.cosXml = cosXmlServer;
|
||||
}
|
||||
|
||||
public void Upload(COSXMLUploadTask uploader)
|
||||
{
|
||||
uploader.InitCosXmlServer(cosXml);
|
||||
uploader.SetDivision(transferConfig.divisionForUpload, transferConfig.sliceSizeForUpload);
|
||||
uploader.Upload();
|
||||
}
|
||||
|
||||
public void Download(COSXMLDownloadTask downloader)
|
||||
{
|
||||
downloader.InitCosXmlServer(cosXml);
|
||||
downloader.Download();
|
||||
}
|
||||
|
||||
public void Copy(COSXMLCopyTask copy)
|
||||
{
|
||||
copy.InitCosXmlServer(cosXml);
|
||||
copy.SetDivision(transferConfig.DdivisionForCopy, transferConfig.sliceSizeForCopy);
|
||||
copy.Copy();
|
||||
}
|
||||
}
|
||||
}
|
||||
630
COSXML/Transfer/XmlBuilder.cs
Normal file
630
COSXML/Transfer/XmlBuilder.cs
Normal file
@@ -0,0 +1,630 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using System.Text;
|
||||
using COSXML.Model.Tag;
|
||||
using System.Xml;
|
||||
using System.IO;
|
||||
using COSXML.Utils;
|
||||
|
||||
namespace COSXML.Transfer
|
||||
{
|
||||
public sealed class XmlBuilder
|
||||
{
|
||||
public static string BuildCORSConfigXML(CORSConfiguration corsConfiguration)
|
||||
{
|
||||
StringWriter stringWriter = new StringWriter();
|
||||
XmlWriterSettings xmlWriterSetting = new XmlWriterSettings();
|
||||
xmlWriterSetting.Indent = true;
|
||||
|
||||
XmlWriter xmlWriter = XmlWriter.Create(stringWriter, xmlWriterSetting);
|
||||
xmlWriter.WriteStartDocument();
|
||||
|
||||
//start to write element
|
||||
xmlWriter.WriteStartElement("CORSConfiguration");
|
||||
if (corsConfiguration.corsRules != null)
|
||||
{
|
||||
foreach(CORSConfiguration.CORSRule corsRule in corsConfiguration.corsRules)
|
||||
{
|
||||
if (corsRule == null) continue;
|
||||
|
||||
xmlWriter.WriteStartElement("CORSRule");
|
||||
|
||||
xmlWriter.WriteElementString("ID", corsRule.id);
|
||||
xmlWriter.WriteElementString("AllowedOrigin", corsRule.allowedOrigin);
|
||||
if (corsRule.allowedMethods != null)
|
||||
{
|
||||
foreach (string method in corsRule.allowedMethods)
|
||||
{
|
||||
xmlWriter.WriteElementString("AllowedMethod", method);
|
||||
}
|
||||
}
|
||||
if (corsRule.allowedHeaders != null)
|
||||
{
|
||||
foreach (string header in corsRule.allowedHeaders)
|
||||
{
|
||||
xmlWriter.WriteElementString("AllowedHeader", header);
|
||||
}
|
||||
}
|
||||
if (corsRule.exposeHeaders != null)
|
||||
{
|
||||
foreach (string exposeHeader in corsRule.exposeHeaders)
|
||||
{
|
||||
xmlWriter.WriteElementString("ExposeHeader", exposeHeader);
|
||||
}
|
||||
}
|
||||
xmlWriter.WriteElementString("MaxAgeSeconds", corsRule.maxAgeSeconds.ToString());
|
||||
|
||||
xmlWriter.WriteEndElement();
|
||||
}
|
||||
}
|
||||
|
||||
// end to element
|
||||
xmlWriter.WriteEndElement();
|
||||
xmlWriter.WriteEndDocument();
|
||||
xmlWriter.Flush();
|
||||
return RemoveXMLHeader(stringWriter.ToString());
|
||||
}
|
||||
|
||||
internal static string BuildWebsiteConfiguration(BucketLoggingStatus bucketLoggingStatus)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public static string BuildLifecycleConfiguration(LifecycleConfiguration lifecycleConfiguration)
|
||||
{
|
||||
StringWriter stringWriter = new StringWriter();
|
||||
XmlWriterSettings xmlWriterSetting = new XmlWriterSettings();
|
||||
xmlWriterSetting.Indent = true;
|
||||
|
||||
XmlWriter xmlWriter = XmlWriter.Create(stringWriter, xmlWriterSetting);
|
||||
xmlWriter.WriteStartDocument();
|
||||
|
||||
//start to write element
|
||||
xmlWriter.WriteStartElement("LifecycleConfiguration");
|
||||
|
||||
if (lifecycleConfiguration.rules != null)
|
||||
{
|
||||
foreach (LifecycleConfiguration.Rule rule in lifecycleConfiguration.rules)
|
||||
{
|
||||
if (rule == null) continue;
|
||||
xmlWriter.WriteStartElement("Rule");
|
||||
if(rule.id != null) xmlWriter.WriteElementString("ID", rule.id);
|
||||
if (rule.filter != null)
|
||||
{
|
||||
xmlWriter.WriteStartElement("Filter");
|
||||
if(rule.filter.prefix != null) xmlWriter.WriteElementString("Prefix", rule.filter.prefix);
|
||||
if (rule.filter.filterAnd != null)
|
||||
{
|
||||
xmlWriter.WriteStartElement("And");
|
||||
if (rule.filter.filterAnd.prefix != null) xmlWriter.WriteElementString("Prefix", rule.filter.filterAnd.prefix);
|
||||
xmlWriter.WriteEndElement();
|
||||
}
|
||||
xmlWriter.WriteEndElement();
|
||||
}
|
||||
if(rule.status != null) xmlWriter.WriteElementString("Status", rule.status);
|
||||
if (rule.transition != null)
|
||||
{
|
||||
xmlWriter.WriteStartElement("Transition");
|
||||
if(rule.transition.days > 0) xmlWriter.WriteElementString("Days", rule.transition.days.ToString());
|
||||
if (rule.transition.storageClass != null) xmlWriter.WriteElementString("StorageClass", rule.transition.storageClass);
|
||||
if (rule.transition.date != null) xmlWriter.WriteElementString("Date", rule.transition.date);
|
||||
xmlWriter.WriteEndElement();
|
||||
}
|
||||
if (rule.expiration != null)
|
||||
{
|
||||
xmlWriter.WriteStartElement("Expiration");
|
||||
if (rule.expiration.days > 0) xmlWriter.WriteElementString("Days", rule.expiration.days.ToString());
|
||||
if (rule.expiration.expiredObjectDeleteMarker != null)
|
||||
{
|
||||
if ((bool)rule.expiration.expiredObjectDeleteMarker)
|
||||
{
|
||||
xmlWriter.WriteElementString("ExpiredObjectDeleteMarker", "true");
|
||||
}
|
||||
else
|
||||
{
|
||||
xmlWriter.WriteElementString("ExpiredObjectDeleteMarker", "false");
|
||||
}
|
||||
}
|
||||
if (rule.expiration.date != null) xmlWriter.WriteElementString("Date", rule.expiration.date);
|
||||
xmlWriter.WriteEndElement();
|
||||
}
|
||||
if (rule.noncurrentVersionTransition != null)
|
||||
{
|
||||
xmlWriter.WriteStartElement("NoncurrentVersionTransition");
|
||||
if(rule.noncurrentVersionTransition.noncurrentDays > 0) xmlWriter.WriteElementString("NoncurrentDays", rule.noncurrentVersionTransition.noncurrentDays.ToString());
|
||||
if(rule.noncurrentVersionTransition.storageClass != null) xmlWriter.WriteElementString("StorageClass", rule.noncurrentVersionTransition.storageClass);
|
||||
xmlWriter.WriteEndElement();
|
||||
}
|
||||
if (rule.noncurrentVersionExpiration != null)
|
||||
{
|
||||
xmlWriter.WriteStartElement("NoncurrentVersionExpiration");
|
||||
if(rule.noncurrentVersionExpiration.noncurrentDays > 0) xmlWriter.WriteElementString("NoncurrentDays", rule.noncurrentVersionExpiration.noncurrentDays.ToString());
|
||||
xmlWriter.WriteEndElement();
|
||||
}
|
||||
if (rule.abortIncompleteMultiUpload != null)
|
||||
{
|
||||
xmlWriter.WriteStartElement("AbortIncompleteMultipartUpload");
|
||||
if (rule.abortIncompleteMultiUpload.daysAfterInitiation > 0) xmlWriter.WriteElementString("DaysAfterInitiation", rule.abortIncompleteMultiUpload.daysAfterInitiation.ToString());
|
||||
xmlWriter.WriteEndElement();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// end to element
|
||||
xmlWriter.WriteEndElement();
|
||||
|
||||
xmlWriter.WriteEndDocument();
|
||||
xmlWriter.Flush();
|
||||
return RemoveXMLHeader(stringWriter.ToString());
|
||||
}
|
||||
|
||||
public static string BuildReplicationConfiguration(ReplicationConfiguration replicationConfiguration)
|
||||
{
|
||||
StringWriter stringWriter = new StringWriter();
|
||||
XmlWriterSettings xmlWriterSetting = new XmlWriterSettings();
|
||||
xmlWriterSetting.Indent = true;
|
||||
|
||||
XmlWriter xmlWriter = XmlWriter.Create(stringWriter, xmlWriterSetting);
|
||||
xmlWriter.WriteStartDocument();
|
||||
|
||||
//start to write element
|
||||
xmlWriter.WriteStartElement("ReplicationConfiguration");
|
||||
|
||||
xmlWriter.WriteElementString("Role", replicationConfiguration.role);
|
||||
|
||||
if(replicationConfiguration.rules != null)
|
||||
{
|
||||
foreach(ReplicationConfiguration.Rule rule in replicationConfiguration.rules)
|
||||
{
|
||||
if(rule == null)continue;
|
||||
|
||||
xmlWriter.WriteStartElement("Rule");
|
||||
|
||||
xmlWriter.WriteElementString("Status", rule.status);
|
||||
xmlWriter.WriteElementString("ID", rule.id);
|
||||
xmlWriter.WriteElementString("Prefix", rule.prefix);
|
||||
if(rule.destination != null){
|
||||
xmlWriter.WriteStartElement("Destination");
|
||||
xmlWriter.WriteElementString("Bucket", rule.destination.bucket);
|
||||
if(rule.destination.storageClass != null) xmlWriter.WriteElementString("StorageClass", rule.destination.storageClass);
|
||||
xmlWriter.WriteEndElement();
|
||||
}
|
||||
xmlWriter.WriteEndElement();
|
||||
}
|
||||
}
|
||||
|
||||
// end to element
|
||||
xmlWriter.WriteEndElement();
|
||||
|
||||
xmlWriter.WriteEndDocument();
|
||||
xmlWriter.Flush();
|
||||
return RemoveXMLHeader(stringWriter.ToString());
|
||||
}
|
||||
|
||||
public static string BuildVersioningConfiguration(VersioningConfiguration versioningConfiguration)
|
||||
{
|
||||
StringWriter stringWriter = new StringWriter();
|
||||
XmlWriterSettings xmlWriterSetting = new XmlWriterSettings();
|
||||
xmlWriterSetting.Indent = true;
|
||||
|
||||
XmlWriter xmlWriter = XmlWriter.Create(stringWriter, xmlWriterSetting);
|
||||
xmlWriter.WriteStartDocument();
|
||||
|
||||
//start to write element
|
||||
xmlWriter.WriteStartElement("VersioningConfiguration");
|
||||
|
||||
xmlWriter.WriteElementString("Status", versioningConfiguration.status);
|
||||
|
||||
// end to element
|
||||
xmlWriter.WriteEndElement();
|
||||
|
||||
xmlWriter.WriteEndDocument();
|
||||
xmlWriter.Flush();
|
||||
return RemoveXMLHeader(stringWriter.ToString());
|
||||
}
|
||||
|
||||
public static string BuildCompleteMultipartUpload(CompleteMultipartUpload completeMultipartUpload)
|
||||
{
|
||||
StringWriter stringWriter = new StringWriter();
|
||||
XmlWriterSettings xmlWriterSetting = new XmlWriterSettings();
|
||||
xmlWriterSetting.Indent = true;
|
||||
|
||||
XmlWriter xmlWriter = XmlWriter.Create(stringWriter, xmlWriterSetting);
|
||||
xmlWriter.WriteStartDocument();
|
||||
|
||||
//start to write element
|
||||
xmlWriter.WriteStartElement("CompleteMultipartUpload");
|
||||
|
||||
if(completeMultipartUpload.parts != null)
|
||||
{
|
||||
foreach(CompleteMultipartUpload.Part part in completeMultipartUpload.parts)
|
||||
{
|
||||
if(part == null)continue;
|
||||
xmlWriter.WriteStartElement("Part");
|
||||
xmlWriter.WriteElementString("PartNumber", part.partNumber.ToString());
|
||||
xmlWriter.WriteElementString("ETag", part.eTag);
|
||||
xmlWriter.WriteEndElement();
|
||||
}
|
||||
}
|
||||
|
||||
// end to element
|
||||
xmlWriter.WriteEndElement();
|
||||
|
||||
xmlWriter.WriteEndDocument();
|
||||
xmlWriter.Flush();
|
||||
return RemoveXMLHeader(stringWriter.ToString());
|
||||
}
|
||||
|
||||
public static string BuildDelete(Delete delete)
|
||||
{
|
||||
StringWriter stringWriter = new StringWriter();
|
||||
XmlWriterSettings xmlWriterSetting = new XmlWriterSettings();
|
||||
xmlWriterSetting.Indent = true;
|
||||
|
||||
XmlWriter xmlWriter = XmlWriter.Create(stringWriter, xmlWriterSetting);
|
||||
xmlWriter.WriteStartDocument();
|
||||
|
||||
//start to write element
|
||||
xmlWriter.WriteStartElement("Delete");
|
||||
xmlWriter.WriteElementString("Quiet", delete.quiet ? "true" : "false");
|
||||
if (delete.deleteObjects != null)
|
||||
{
|
||||
foreach(Delete.DeleteObject deleteObject in delete.deleteObjects)
|
||||
{
|
||||
if(deleteObject == null)continue;
|
||||
xmlWriter.WriteStartElement("Object");
|
||||
xmlWriter.WriteElementString("Key", deleteObject.key);
|
||||
if(deleteObject.versionId != null) xmlWriter.WriteElementString("VersionId", deleteObject.versionId);
|
||||
xmlWriter.WriteEndElement();
|
||||
}
|
||||
}
|
||||
|
||||
// end to element
|
||||
xmlWriter.WriteEndElement();
|
||||
|
||||
xmlWriter.WriteEndDocument();
|
||||
xmlWriter.Flush();
|
||||
return RemoveXMLHeader(stringWriter.ToString());
|
||||
}
|
||||
|
||||
public static string BuildRestoreConfigure(RestoreConfigure restoreConfigure)
|
||||
{
|
||||
StringWriter stringWriter = new StringWriter();
|
||||
XmlWriterSettings xmlWriterSetting = new XmlWriterSettings();
|
||||
xmlWriterSetting.Indent = true;
|
||||
|
||||
XmlWriter xmlWriter = XmlWriter.Create(stringWriter, xmlWriterSetting);
|
||||
xmlWriter.WriteStartDocument();
|
||||
|
||||
//start to write element
|
||||
xmlWriter.WriteStartElement("RestoreRequest");
|
||||
|
||||
xmlWriter.WriteElementString("Days", restoreConfigure.days.ToString());
|
||||
if (restoreConfigure.casJobParameters != null)
|
||||
{
|
||||
xmlWriter.WriteStartElement("CASJobParameters");
|
||||
xmlWriter.WriteElementString("Tier", EnumUtils.GetValue(restoreConfigure.casJobParameters.tier));
|
||||
xmlWriter.WriteEndElement();
|
||||
}
|
||||
|
||||
// end to element
|
||||
xmlWriter.WriteEndElement();
|
||||
|
||||
xmlWriter.WriteEndDocument();
|
||||
xmlWriter.Flush();
|
||||
return RemoveXMLHeader(stringWriter.ToString());
|
||||
}
|
||||
|
||||
public static string BuildWebsiteConfiguration(WebsiteConfiguration websiteConfiguration)
|
||||
{
|
||||
StringWriter stringWriter = new StringWriter();
|
||||
XmlWriterSettings xmlWriterSetting = new XmlWriterSettings();
|
||||
xmlWriterSetting.Indent = true;
|
||||
|
||||
XmlWriter xmlWriter = XmlWriter.Create(stringWriter, xmlWriterSetting);
|
||||
xmlWriter.WriteStartDocument();
|
||||
xmlWriter.WriteStartElement("WebsiteConfiguration");
|
||||
|
||||
if (websiteConfiguration.indexDocument != null)
|
||||
{
|
||||
xmlWriter.WriteStartElement("IndexDocument");
|
||||
xmlWriter.WriteElementString("Suffix", websiteConfiguration.indexDocument.suffix);
|
||||
xmlWriter.WriteEndElement();
|
||||
}
|
||||
|
||||
if (websiteConfiguration.errorDocument != null)
|
||||
{
|
||||
xmlWriter.WriteStartElement("ErrorDocument");
|
||||
xmlWriter.WriteElementString("Key", websiteConfiguration.errorDocument.key);
|
||||
xmlWriter.WriteEndElement();
|
||||
}
|
||||
|
||||
if (websiteConfiguration.redirectAllRequestTo != null)
|
||||
{
|
||||
xmlWriter.WriteStartElement("RedirectAllRequestTo");
|
||||
xmlWriter.WriteElementString("Protocol", websiteConfiguration.redirectAllRequestTo.protocol);
|
||||
xmlWriter.WriteEndElement();
|
||||
}
|
||||
|
||||
if (websiteConfiguration.routingRules != null && websiteConfiguration.routingRules.Count > 0)
|
||||
{
|
||||
xmlWriter.WriteStartElement("RoutingRules");
|
||||
foreach (WebsiteConfiguration.RoutingRule routingRule in websiteConfiguration.routingRules)
|
||||
{
|
||||
xmlWriter.WriteStartElement("RoutingRule");
|
||||
if (routingRule.contidion != null)
|
||||
{
|
||||
xmlWriter.WriteStartElement("Condition");
|
||||
xmlWriter.WriteElementString("HttpErrorCodeReturnedEquals", routingRule.contidion.httpErrorCodeReturnedEquals.ToString());
|
||||
xmlWriter.WriteElementString("KeyPrefixEquals", routingRule.contidion.keyPrefixEquals);
|
||||
xmlWriter.WriteEndElement();
|
||||
}
|
||||
if (routingRule.redirect != null)
|
||||
{
|
||||
xmlWriter.WriteStartElement("Redirect");
|
||||
xmlWriter.WriteElementString("Protocol", routingRule.redirect.protocol);
|
||||
xmlWriter.WriteElementString("ReplaceKeyPrefixWith", routingRule.redirect.replaceKeyPrefixWith);
|
||||
xmlWriter.WriteElementString("ReplaceKeyWith", routingRule.redirect.replaceKeyWith);
|
||||
xmlWriter.WriteEndElement();
|
||||
}
|
||||
xmlWriter.WriteEndElement();
|
||||
}
|
||||
xmlWriter.WriteEndElement();
|
||||
}
|
||||
// end to element
|
||||
xmlWriter.WriteEndElement();
|
||||
|
||||
xmlWriter.WriteEndDocument();
|
||||
xmlWriter.Flush();
|
||||
return RemoveXMLHeader(stringWriter.ToString());
|
||||
}
|
||||
|
||||
public static string BuildBucketLogging(BucketLoggingStatus bucketLoggingStatus)
|
||||
{
|
||||
StringWriter stringWriter = new StringWriter();
|
||||
XmlWriterSettings xmlWriterSetting = new XmlWriterSettings();
|
||||
xmlWriterSetting.Indent = true;
|
||||
|
||||
XmlWriter xmlWriter = XmlWriter.Create(stringWriter, xmlWriterSetting);
|
||||
xmlWriter.WriteStartDocument();
|
||||
|
||||
//start to write element
|
||||
xmlWriter.WriteStartElement("BucketLoggingStatus");
|
||||
if (bucketLoggingStatus.loggingEnabled != null)
|
||||
{
|
||||
xmlWriter.WriteStartElement("LoggingEnabled");
|
||||
if(bucketLoggingStatus.loggingEnabled.targetBucket != null)
|
||||
xmlWriter.WriteElementString("TargetBucket", bucketLoggingStatus.loggingEnabled.targetBucket);
|
||||
if(bucketLoggingStatus.loggingEnabled.targetPrefix != null)
|
||||
xmlWriter.WriteElementString("TargetPrefix", bucketLoggingStatus.loggingEnabled.targetPrefix);
|
||||
xmlWriter.WriteEndElement();
|
||||
}
|
||||
|
||||
// end to element
|
||||
xmlWriter.WriteEndElement();
|
||||
|
||||
xmlWriter.WriteEndDocument();
|
||||
xmlWriter.Flush();
|
||||
return RemoveXMLHeader(stringWriter.ToString());
|
||||
}
|
||||
|
||||
public static string BuildInventoryConfiguration(InventoryConfiguration inventoryConfiguration)
|
||||
{
|
||||
StringWriter stringWriter = new StringWriter();
|
||||
XmlWriterSettings xmlWriterSetting = new XmlWriterSettings();
|
||||
xmlWriterSetting.Indent = true;
|
||||
|
||||
XmlWriter xmlWriter = XmlWriter.Create(stringWriter, xmlWriterSetting);
|
||||
xmlWriter.WriteStartDocument();
|
||||
xmlWriter.WriteStartElement("InventoryConfiguration");
|
||||
|
||||
if (inventoryConfiguration.id != null)
|
||||
xmlWriter.WriteElementString( "Id", inventoryConfiguration.id);
|
||||
xmlWriter.WriteElementString("IsEnabled", inventoryConfiguration.isEnabled ? "true" : "false");
|
||||
if (inventoryConfiguration.destination != null)
|
||||
{
|
||||
xmlWriter.WriteStartElement("Destination");
|
||||
if (inventoryConfiguration.destination.cosBucketDestination != null)
|
||||
{
|
||||
xmlWriter.WriteStartElement("COSBucketDestination");
|
||||
if (inventoryConfiguration.destination.cosBucketDestination.format != null)
|
||||
xmlWriter.WriteElementString("Format", inventoryConfiguration.destination.cosBucketDestination.format);
|
||||
if (inventoryConfiguration.destination.cosBucketDestination.accountId != null)
|
||||
xmlWriter.WriteElementString("AccountId", inventoryConfiguration.destination.cosBucketDestination.accountId);
|
||||
if (inventoryConfiguration.destination.cosBucketDestination.bucket != null)
|
||||
xmlWriter.WriteElementString("Bucket", inventoryConfiguration.destination.cosBucketDestination.bucket);
|
||||
if (inventoryConfiguration.destination.cosBucketDestination.prefix != null)
|
||||
{
|
||||
xmlWriter.WriteElementString("Prefix", inventoryConfiguration.destination.cosBucketDestination.prefix);
|
||||
}
|
||||
if (inventoryConfiguration.destination.cosBucketDestination.encryption != null)
|
||||
{
|
||||
xmlWriter.WriteStartElement("Encryption");
|
||||
xmlWriter.WriteElementString("SSE-COS", inventoryConfiguration.destination.cosBucketDestination.encryption.sSECOS);
|
||||
xmlWriter.WriteEndElement();
|
||||
}
|
||||
xmlWriter.WriteEndElement();
|
||||
}
|
||||
xmlWriter.WriteEndElement();
|
||||
}
|
||||
if (inventoryConfiguration.schedule != null && inventoryConfiguration.schedule.frequency != null)
|
||||
{
|
||||
xmlWriter.WriteStartElement("Schedule");
|
||||
xmlWriter.WriteElementString("Frequency", inventoryConfiguration.schedule.frequency);
|
||||
xmlWriter.WriteEndElement();
|
||||
}
|
||||
if (inventoryConfiguration.filter != null && inventoryConfiguration.filter.prefix != null)
|
||||
{
|
||||
xmlWriter.WriteStartElement("Filter");
|
||||
xmlWriter.WriteElementString("Prefix", inventoryConfiguration.filter.prefix);
|
||||
xmlWriter.WriteEndElement();
|
||||
}
|
||||
if (inventoryConfiguration.includedObjectVersions != null)
|
||||
{
|
||||
xmlWriter.WriteElementString("IncludedObjectVersions", inventoryConfiguration.includedObjectVersions);
|
||||
}
|
||||
if (inventoryConfiguration.optionalFields != null && inventoryConfiguration.optionalFields.fields != null)
|
||||
{
|
||||
xmlWriter.WriteStartElement("OptionalFields");
|
||||
foreach (string field in inventoryConfiguration.optionalFields.fields)
|
||||
{
|
||||
xmlWriter.WriteElementString("Field", field);
|
||||
}
|
||||
xmlWriter.WriteEndElement();
|
||||
}
|
||||
|
||||
// end to element
|
||||
xmlWriter.WriteEndElement();
|
||||
|
||||
xmlWriter.WriteEndDocument();
|
||||
xmlWriter.Flush();
|
||||
return RemoveXMLHeader(stringWriter.ToString());
|
||||
|
||||
}
|
||||
|
||||
public static string BuildTagging(Tagging tagging) {
|
||||
StringWriter stringWriter = new StringWriter();
|
||||
XmlWriterSettings xmlWriterSetting = new XmlWriterSettings();
|
||||
xmlWriterSetting.Indent = true;
|
||||
|
||||
XmlWriter xmlWriter = XmlWriter.Create(stringWriter, xmlWriterSetting);
|
||||
xmlWriter.WriteStartDocument();
|
||||
|
||||
//start to write element
|
||||
xmlWriter.WriteStartElement("Tagging");
|
||||
xmlWriter.WriteStartElement("TagSet");
|
||||
if (tagging.tagSet.tags.Count > 0) {
|
||||
foreach (Tagging.Tag tag in tagging.tagSet.tags) {
|
||||
xmlWriter.WriteStartElement("Tag");
|
||||
xmlWriter.WriteElementString("Key", tag.key);
|
||||
xmlWriter.WriteElementString("Value", tag.value);
|
||||
xmlWriter.WriteEndElement();
|
||||
}
|
||||
}
|
||||
|
||||
// end to element
|
||||
xmlWriter.WriteEndElement();
|
||||
xmlWriter.WriteEndElement();
|
||||
|
||||
xmlWriter.WriteEndDocument();
|
||||
xmlWriter.Flush();
|
||||
return RemoveXMLHeader(stringWriter.ToString());
|
||||
}
|
||||
|
||||
public static string BuildDomain(DomainConfiguration domain) {
|
||||
StringWriter stringWriter = new StringWriter();
|
||||
XmlWriterSettings xmlWriterSetting = new XmlWriterSettings();
|
||||
xmlWriterSetting.Indent = true;
|
||||
|
||||
XmlWriter xmlWriter = XmlWriter.Create(stringWriter, xmlWriterSetting);
|
||||
xmlWriter.WriteStartDocument();
|
||||
|
||||
//start to write element
|
||||
xmlWriter.WriteStartElement("DomainConfiguration");
|
||||
xmlWriter.WriteStartElement("DomainRule");
|
||||
|
||||
if (domain.rule != null) {
|
||||
|
||||
xmlWriter.WriteElementString("Status", domain.rule.Status);
|
||||
xmlWriter.WriteElementString("Name", domain.rule.Name);
|
||||
xmlWriter.WriteElementString("Type", domain.rule.Type);
|
||||
if (domain.rule.Replace != null) {
|
||||
xmlWriter.WriteElementString("Replace", domain.rule.Replace);
|
||||
}
|
||||
}
|
||||
|
||||
// end to element
|
||||
xmlWriter.WriteEndElement();
|
||||
xmlWriter.WriteEndElement();
|
||||
|
||||
xmlWriter.WriteEndDocument();
|
||||
xmlWriter.Flush();
|
||||
return RemoveXMLHeader(stringWriter.ToString());
|
||||
}
|
||||
|
||||
public static string BuildSelection(string expression, string expressionType,
|
||||
ObjectSelectionFormat inputFormat, ObjectSelectionFormat outputFormat, bool notifyProgress) {
|
||||
StringWriter stringWriter = new StringWriter();
|
||||
XmlWriterSettings xmlWriterSetting = new XmlWriterSettings();
|
||||
xmlWriterSetting.Indent = true;
|
||||
|
||||
XmlWriter xmlWriter = XmlWriter.Create(stringWriter, xmlWriterSetting);
|
||||
xmlWriter.WriteStartDocument();
|
||||
|
||||
//start to write element
|
||||
xmlWriter.WriteStartElement("SelectRequest");
|
||||
xmlWriter.WriteElementString("Expression", expression);
|
||||
xmlWriter.WriteElementString("ExpressionType", expressionType);
|
||||
|
||||
if (inputFormat != null) {
|
||||
xmlWriter.WriteStartElement("InputSerialization");
|
||||
writeStringIfValuePresent(xmlWriter, "CompressionType", inputFormat.CompressionType);
|
||||
if (inputFormat.csvFormat != null) {
|
||||
xmlWriter.WriteStartElement("CSV");
|
||||
writeStringIfValuePresent(xmlWriter, "FileHeaderInfo", inputFormat.csvFormat.FileHeaderInfo);
|
||||
writeStringIfValuePresent(xmlWriter, "RecordDelimiter", inputFormat.csvFormat.RecordDelimiter);
|
||||
writeStringIfValuePresent(xmlWriter, "FieldDelimiter", inputFormat.csvFormat.FieldDelimiter);
|
||||
writeStringIfValuePresent(xmlWriter, "QuoteCharacter", inputFormat.csvFormat.QuoteCharacter);
|
||||
writeStringIfValuePresent(xmlWriter, "QuoteEscapeCharacter", inputFormat.csvFormat.QuoteEscapeCharacter);
|
||||
writeStringIfValuePresent(xmlWriter, "Comments", inputFormat.csvFormat.Comments);
|
||||
writeStringIfValuePresent(xmlWriter, "AllowQuotedRecordDelimiter",
|
||||
inputFormat.csvFormat.AllowQuotedRecordDelimiter ? "TRUE" : "FALSE");
|
||||
xmlWriter.WriteEndElement();
|
||||
} else if (inputFormat.jsonFormat != null) {
|
||||
xmlWriter.WriteStartElement("JSON");
|
||||
writeStringIfValuePresent(xmlWriter, "Type", inputFormat.jsonFormat.Type);
|
||||
xmlWriter.WriteEndElement();
|
||||
}
|
||||
xmlWriter.WriteEndElement();
|
||||
}
|
||||
|
||||
if (outputFormat != null) {
|
||||
xmlWriter.WriteStartElement("OutputSerialization");
|
||||
if (outputFormat.csvFormat != null) {
|
||||
xmlWriter.WriteStartElement("CSV");
|
||||
writeStringIfValuePresent(xmlWriter, "QuoteFields", outputFormat.csvFormat.QuoteFields);
|
||||
writeStringIfValuePresent(xmlWriter, "RecordDelimiter", outputFormat.csvFormat.RecordDelimiter);
|
||||
writeStringIfValuePresent(xmlWriter, "FieldDelimiter", outputFormat.csvFormat.FieldDelimiter);
|
||||
writeStringIfValuePresent(xmlWriter, "QuoteCharacter", outputFormat.csvFormat.QuoteCharacter);
|
||||
writeStringIfValuePresent(xmlWriter, "QuoteEscapeCharacter", outputFormat.csvFormat.QuoteEscapeCharacter);
|
||||
xmlWriter.WriteEndElement();
|
||||
} else if (outputFormat.jsonFormat != null) {
|
||||
xmlWriter.WriteStartElement("JSON");
|
||||
writeStringIfValuePresent(xmlWriter, "RecordDelimiter", outputFormat.jsonFormat.RecordDelimiter);
|
||||
xmlWriter.WriteEndElement();
|
||||
}
|
||||
xmlWriter.WriteEndElement();
|
||||
}
|
||||
|
||||
xmlWriter.WriteStartElement("RequestProgress");
|
||||
xmlWriter.WriteElementString("Enabled", notifyProgress ? "TRUE" : "FALSE");
|
||||
xmlWriter.WriteEndElement();
|
||||
|
||||
xmlWriter.WriteEndDocument();
|
||||
xmlWriter.Flush();
|
||||
return RemoveXMLHeader(stringWriter.ToString());
|
||||
}
|
||||
|
||||
private static void writeStringIfValuePresent(XmlWriter xmlWriter, String elementName,
|
||||
String elementValue) {
|
||||
if (elementValue != null && elementValue.Length > 0) {
|
||||
xmlWriter.WriteElementString(elementName, elementValue);
|
||||
}
|
||||
}
|
||||
|
||||
private static string RemoveXMLHeader(string xmlContent)
|
||||
{
|
||||
if (xmlContent != null)
|
||||
{
|
||||
if (xmlContent.StartsWith("<?xml"))
|
||||
{
|
||||
int end = xmlContent.IndexOf("?>");
|
||||
xmlContent = xmlContent.Substring(end + 2);
|
||||
}
|
||||
}
|
||||
return xmlContent;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
1782
COSXML/Transfer/XmlParse.cs
Normal file
1782
COSXML/Transfer/XmlParse.cs
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user