代码修改后的版本,全部提交
This commit is contained in:
68
COSXML/Model/Object/AbortMultipartUploadRequest.cs
Normal file
68
COSXML/Model/Object/AbortMultipartUploadRequest.cs
Normal file
@@ -0,0 +1,68 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using System.Text;
|
||||
using COSXML.Common;
|
||||
using COSXML.CosException;
|
||||
|
||||
namespace COSXML.Model.Object
|
||||
{
|
||||
/// <summary>
|
||||
/// 舍弃一个分块上传并删除已上传的块
|
||||
/// <see cref="https://cloud.tencent.com/document/product/436/7740"/>
|
||||
/// </summary>
|
||||
public sealed class AbortMultipartUploadRequest : ObjectRequest
|
||||
{
|
||||
/// <summary>
|
||||
/// 分片块的UploadId,使用 Initiate Multipart Upload 接口初始化分片上传时会得到一个 uploadId,该 ID 不但唯一标识这一分块数据,也标识了这分块数据在整个文件内的相对位置
|
||||
/// </summary>
|
||||
private string uploadId;
|
||||
|
||||
public AbortMultipartUploadRequest(string bucket, string key, string uploadId)
|
||||
: base(bucket, key)
|
||||
{
|
||||
this.uploadId = uploadId;
|
||||
this.method = CosRequestMethod.DELETE;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 分片块上传的UploadId
|
||||
/// </summary>
|
||||
/// <param name="uploadId"></param>
|
||||
public void SetUploadId(string uploadId)
|
||||
{
|
||||
this.uploadId = uploadId;
|
||||
}
|
||||
/// <summary>
|
||||
/// 分片块上传的UploadId
|
||||
/// </summary>
|
||||
/// <returns>uploadId</returns>
|
||||
public string GetUploadId()
|
||||
{
|
||||
return uploadId;
|
||||
}
|
||||
|
||||
public override void CheckParameters()
|
||||
{
|
||||
if (requestUrlWithSign != null) return;
|
||||
base.CheckParameters();
|
||||
if (uploadId == null)
|
||||
{
|
||||
throw new CosClientException((int)CosClientError.INVALID_ARGUMENT, "uploadId is null");
|
||||
}
|
||||
}
|
||||
|
||||
protected override void InternalUpdateQueryParameters()
|
||||
{
|
||||
try
|
||||
{
|
||||
this.queryParameters.Add("uploadId", uploadId);
|
||||
}
|
||||
catch (ArgumentException)
|
||||
{
|
||||
this.queryParameters["uploadId"] = uploadId;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
15
COSXML/Model/Object/AbortMultipartUploadResult.cs
Normal file
15
COSXML/Model/Object/AbortMultipartUploadResult.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using System.Text;
|
||||
|
||||
namespace COSXML.Model.Object
|
||||
{
|
||||
/// <summary>
|
||||
/// 舍弃一个分块上传并删除已上传的块返回的结果
|
||||
/// <see cref="https://cloud.tencent.com/document/product/436/7740"/>
|
||||
/// </summary>
|
||||
public sealed class AbortMultipartUploadResult : CosResult
|
||||
{
|
||||
}
|
||||
}
|
||||
114
COSXML/Model/Object/CompleteMultipartUploadRequest.cs
Normal file
114
COSXML/Model/Object/CompleteMultipartUploadRequest.cs
Normal file
@@ -0,0 +1,114 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using System.Text;
|
||||
using COSXML.Model.Tag;
|
||||
using COSXML.Common;
|
||||
using COSXML.CosException;
|
||||
using COSXML.Network;
|
||||
|
||||
namespace COSXML.Model.Object
|
||||
{
|
||||
/// <summary>
|
||||
/// 实现完成整个分块上传
|
||||
/// <see cref="https://cloud.tencent.com/document/product/436/7742"/>
|
||||
/// </summary>
|
||||
public sealed class CompleteMultipartUploadRequest : ObjectRequest
|
||||
{
|
||||
/// <summary>
|
||||
/// 本次分块上传的所有信息
|
||||
/// <see cref="Model.Tag.CompleteMultipartUpload"/>
|
||||
/// </summary>
|
||||
private CompleteMultipartUpload completeMultipartUpload;
|
||||
/// <summary>
|
||||
/// 标识本次分块上传的 ID,
|
||||
/// 使用 Initiate Multipart Upload 接口初始化分片上传时会得到一个 uploadId,
|
||||
/// 该 ID 不但唯一标识这一分块数据,也标识了这分块数据在整个文件内的相对位置
|
||||
/// </summary>
|
||||
private string uploadId;
|
||||
|
||||
public CompleteMultipartUploadRequest(string bucket, string key, string uploadId)
|
||||
: base(bucket, key)
|
||||
{
|
||||
this.method = CosRequestMethod.POST;
|
||||
this.needMD5 = true;
|
||||
this.uploadId = uploadId;
|
||||
completeMultipartUpload = new CompleteMultipartUpload();
|
||||
completeMultipartUpload.parts = new List<CompleteMultipartUpload.Part>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 标识本次分块上传的 ID,
|
||||
/// 使用 Initiate Multipart Upload 接口初始化分片上传时会得到一个 uploadId,
|
||||
/// 该 ID 不但唯一标识这一分块数据,也标识了这分块数据在整个文件内的相对位置
|
||||
/// </summary>
|
||||
/// <param name="uploadId"></param>
|
||||
public void SetUploadId(string uploadId)
|
||||
{
|
||||
this.uploadId = uploadId;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 添加分片块(块编号,块ETag值)
|
||||
/// </summary>
|
||||
/// <param name="partNumber"></param>
|
||||
/// <param name="eTag"></param>
|
||||
public void SetPartNumberAndETag(int partNumber, string eTag)
|
||||
{
|
||||
CompleteMultipartUpload.Part part = new CompleteMultipartUpload.Part();
|
||||
part.partNumber = partNumber;
|
||||
part.eTag = eTag;
|
||||
completeMultipartUpload.parts.Add(part);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 添加分片块(块编号,块ETag值)
|
||||
/// </summary>
|
||||
/// <param name="partNumberAndETags"></param>
|
||||
public void SetPartNumberAndETag(Dictionary<int, string> partNumberAndETags)
|
||||
{
|
||||
if (partNumberAndETags != null)
|
||||
{
|
||||
foreach (KeyValuePair<int, string> pair in partNumberAndETags)
|
||||
{
|
||||
SetPartNumberAndETag(pair.Key, pair.Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override Network.RequestBody GetRequestBody()
|
||||
{
|
||||
string content = Transfer.XmlBuilder.BuildCompleteMultipartUpload(completeMultipartUpload);
|
||||
byte[] data = Encoding.UTF8.GetBytes(content);
|
||||
ByteRequestBody body = new ByteRequestBody(data);
|
||||
return body;
|
||||
}
|
||||
|
||||
public override void CheckParameters()
|
||||
{
|
||||
if (completeMultipartUpload.parts.Count == 0)
|
||||
{
|
||||
throw new CosClientException((int)CosClientError.INVALID_ARGUMENT, "completeMultipartUpload.parts count = 0");
|
||||
}
|
||||
if (requestUrlWithSign != null) return;
|
||||
base.CheckParameters();
|
||||
if (uploadId == null)
|
||||
{
|
||||
throw new CosClientException((int)CosClientError.INVALID_ARGUMENT, "uploadId is null");
|
||||
}
|
||||
}
|
||||
|
||||
protected override void InternalUpdateQueryParameters()
|
||||
{
|
||||
try
|
||||
{
|
||||
this.queryParameters.Add("uploadId", uploadId);
|
||||
}
|
||||
catch (ArgumentException)
|
||||
{
|
||||
this.queryParameters["uploadId"] = uploadId;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
33
COSXML/Model/Object/CompleteMultipartUploadResult.cs
Normal file
33
COSXML/Model/Object/CompleteMultipartUploadResult.cs
Normal file
@@ -0,0 +1,33 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using System.Text;
|
||||
using COSXML.Model.Tag;
|
||||
using COSXML.Transfer;
|
||||
|
||||
namespace COSXML.Model.Object
|
||||
{
|
||||
/// <summary>
|
||||
/// 完成整个分块上传返回的结果
|
||||
/// <see cref="https://cloud.tencent.com/document/product/436/7742"/>
|
||||
/// </summary>
|
||||
public sealed class CompleteMultipartUploadResult : CosResult
|
||||
{
|
||||
/// <summary>
|
||||
/// Complete返回信息
|
||||
/// <see cref="Model.Tag.CompleteResult"/>
|
||||
/// </summary>
|
||||
public CompleteResult completeResult;
|
||||
|
||||
internal override void ParseResponseBody(System.IO.Stream inputStream, string contentType, long contentLength)
|
||||
{
|
||||
completeResult = new CompleteResult();
|
||||
XmlParse.ParseCompleteMultipartUploadResult(inputStream, completeResult);
|
||||
}
|
||||
|
||||
public override string GetResultInfo()
|
||||
{
|
||||
return base.GetResultInfo() + (completeResult == null ? "" : "\n" + completeResult.GetInfo());
|
||||
}
|
||||
}
|
||||
}
|
||||
192
COSXML/Model/Object/CopyObjectRequest.cs
Normal file
192
COSXML/Model/Object/CopyObjectRequest.cs
Normal file
@@ -0,0 +1,192 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using System.Text;
|
||||
using COSXML.Common;
|
||||
using COSXML.CosException;
|
||||
using COSXML.Model.Tag;
|
||||
using COSXML.Utils;
|
||||
|
||||
namespace COSXML.Model.Object
|
||||
{
|
||||
/// <summary>
|
||||
/// 实现将一个文件从源路径复制到目标路径
|
||||
/// <see cref="https://cloud.tencent.com/document/product/436/10881"/>
|
||||
/// </summary>
|
||||
public sealed class CopyObjectRequest : ObjectRequest
|
||||
{
|
||||
/// <summary>
|
||||
/// 拷贝的对象源
|
||||
/// <see cref="Model.Tag.CopySourceStruct"/>
|
||||
/// </summary>
|
||||
private CopySourceStruct copySourceStruct;
|
||||
|
||||
public CopyObjectRequest(string bucket, string key)
|
||||
: base(bucket, key)
|
||||
{
|
||||
this.method = CosRequestMethod.PUT;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置复制的对象源
|
||||
/// <see cref="Model.Tag.CopySourceStruct"/>
|
||||
/// </summary>
|
||||
/// <param name="copySource"></param>
|
||||
public void SetCopySource(CopySourceStruct copySource)
|
||||
{
|
||||
this.copySourceStruct = copySource;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 是否拷贝源文件的元数据,枚举值:Copy, Replaced,默认值 Copy。
|
||||
/// 假如标记为 Copy,则拷贝源文件的元数据;
|
||||
/// 假如标记为 Replaced,则按本次请求的 Header 信息修改元数据。
|
||||
/// 当目标路径和源路径一致,即用户试图修改元数据时,则标记必须为 Replaced
|
||||
/// </summary>
|
||||
/// <param name="metaDataDirective"></param>
|
||||
public void SetCopyMetaDataDirective(CosMetaDataDirective metaDataDirective)
|
||||
{
|
||||
SetRequestHeader(CosRequestHeaderKey.X_COS_METADATA_DIRECTIVE, EnumUtils.GetValue(metaDataDirective));
|
||||
}
|
||||
/// <summary>
|
||||
/// 当 Object 在指定时间后被修改,则执行操作,否则返回 412。
|
||||
/// 可与 x-cos-copy-source-If-None-Match 一起使用,与其他条件联合使用返回冲突
|
||||
/// </summary>
|
||||
/// <param name="sourceIfModifiedSince"></param>
|
||||
public void SetCopyIfModifiedSince(string sourceIfModifiedSince)
|
||||
{
|
||||
if (sourceIfModifiedSince != null)
|
||||
{
|
||||
SetRequestHeader(CosRequestHeaderKey.X_COS_COPY_SOURCE_IF_MODIFIED_SINCE, sourceIfModifiedSince);
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 当 Object 在指定时间后未被修改,则执行操作,否则返回 412。
|
||||
/// 可与 x-cos-copy-source-If-Match 一起使用,与其他条件联合使用返回冲突。
|
||||
/// </summary>
|
||||
/// <param name="sourceIfUnmodifiedSince"></param>
|
||||
public void SetCopyIfUnmodifiedSince(string sourceIfUnmodifiedSince)
|
||||
{
|
||||
if (sourceIfUnmodifiedSince != null)
|
||||
{
|
||||
SetRequestHeader(CosRequestHeaderKey.X_COS_COPY_SOURCE_IF_UNMODIFIED_SINCE, sourceIfUnmodifiedSince);
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Object 的 Etag 和给定一致时,则执行操作,否则返回 412。
|
||||
/// 可与 x-cos-copy-source-If-Unmodified-Since 一起使用,与其他条件联合使用返回冲突。
|
||||
/// </summary>
|
||||
/// <param name="eTag"></param>
|
||||
public void SetCopyIfMatch(string eTag)
|
||||
{
|
||||
if (eTag != null)
|
||||
{
|
||||
SetRequestHeader(CosRequestHeaderKey.X_COS_COPY_SOURCE_IF_MATCH, eTag);
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 当 Object 的 Etag 和给定不一致时,则执行操作,否则返回 412。
|
||||
/// 可与 x-cos-copy-source-If-Modified-Since 一起使用,与其他条件联合使用返回冲突
|
||||
/// </summary>
|
||||
/// <param name="eTag"></param>
|
||||
public void SetCopyIfNoneMatch(string eTag)
|
||||
{
|
||||
if (eTag != null)
|
||||
{
|
||||
SetRequestHeader(CosRequestHeaderKey.X_COS_COPY_SOURCE_IF_NONE_MATCH, eTag);
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 设置 Object 的存储级别,枚举值:STANDARD,STANDARD_IA。默认值:STANDARD
|
||||
/// <see cref="Common.CosStorageClass"/>
|
||||
/// </summary>
|
||||
/// <param name="cosStorageClass"></param>
|
||||
public void SetCosStorageClass(CosStorageClass cosStorageClass)
|
||||
{
|
||||
SetRequestHeader(CosRequestHeaderKey.X_COS_STORAGE_CLASS_, EnumUtils.GetValue(cosStorageClass));
|
||||
}
|
||||
/// <summary>
|
||||
/// 定义 Object 的 ACL 属性。有效值:private,public-read-write,public-read;默认值:private
|
||||
/// <see cref="Common.CosACL"/>
|
||||
/// </summary>
|
||||
/// <param name="cosACL"></param>
|
||||
public void SetCosACL(string cosACL)
|
||||
{
|
||||
if (cosACL != null)
|
||||
{
|
||||
SetRequestHeader(CosRequestHeaderKey.X_COS_ACL, cosACL);
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 定义 Object 的 ACL 属性。有效值:private,public-read-write,public-read;默认值:private
|
||||
/// <see cref="Common.CosACL"/>
|
||||
/// </summary>
|
||||
/// <param name="cosACL"></param>
|
||||
public void SetCosACL(CosACL cosACL)
|
||||
{
|
||||
SetRequestHeader(CosRequestHeaderKey.X_COS_ACL, EnumUtils.GetValue(cosACL));
|
||||
}
|
||||
/// <summary>
|
||||
/// 赋予被授权者读的权限
|
||||
/// <see cref="Model.Tag.GrantAccount"/>
|
||||
/// </summary>
|
||||
/// <param name="grantAccount"></param>
|
||||
public void SetXCosGrantRead(GrantAccount grantAccount)
|
||||
{
|
||||
if (grantAccount != null)
|
||||
{
|
||||
SetRequestHeader(CosRequestHeaderKey.X_COS_GRANT_READ, grantAccount.GetGrantAccounts());
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 赋予被授权者写的权限
|
||||
/// <see cref="Model.Tag.GrantAccount"/>
|
||||
/// </summary>
|
||||
/// <param name="grantAccount"></param>
|
||||
public void SetXCosGrantWrite(GrantAccount grantAccount)
|
||||
{
|
||||
if (grantAccount != null)
|
||||
{
|
||||
SetRequestHeader(CosRequestHeaderKey.X_COS_GRANT_WRITE, grantAccount.GetGrantAccounts());
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 赋予被授权者所有的权限
|
||||
/// <see cref="Model.Tag.GrantAccount"/>
|
||||
/// </summary>
|
||||
/// <param name="grantAccount"></param>
|
||||
public void SetXCosReadWrite(GrantAccount grantAccount)
|
||||
{
|
||||
if (grantAccount != null)
|
||||
{
|
||||
SetRequestHeader(CosRequestHeaderKey.X_COS_GRANT_FULL_CONTROL, grantAccount.GetGrantAccounts());
|
||||
}
|
||||
}
|
||||
|
||||
public override void CheckParameters()
|
||||
{
|
||||
if (copySourceStruct == null)
|
||||
{
|
||||
throw new CosClientException((int)CosClientError.INVALID_ARGUMENT, "copy source is null");
|
||||
}
|
||||
else
|
||||
{
|
||||
copySourceStruct.CheckParameters();
|
||||
}
|
||||
base.CheckParameters();
|
||||
}
|
||||
|
||||
protected override void InteranlUpdateHeaders()
|
||||
{
|
||||
try
|
||||
{
|
||||
this.headers.Add(CosRequestHeaderKey.X_COS_COPY_SOURCE, copySourceStruct.GetCopySouce());
|
||||
}
|
||||
catch (ArgumentException)
|
||||
{
|
||||
this.headers[CosRequestHeaderKey.X_COS_COPY_SOURCE] = copySourceStruct.GetCopySouce();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
34
COSXML/Model/Object/CopyObjectResult.cs
Normal file
34
COSXML/Model/Object/CopyObjectResult.cs
Normal file
@@ -0,0 +1,34 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using System.Text;
|
||||
using COSXML.Model.Tag;
|
||||
using COSXML.Transfer;
|
||||
|
||||
namespace COSXML.Model.Object
|
||||
{
|
||||
/// <summary>
|
||||
/// 复制对象返回的结果
|
||||
/// <see cref="https://cloud.tencent.com/document/product/436/10881"/>
|
||||
/// </summary>
|
||||
public sealed class CopyObjectResult : CosResult
|
||||
{
|
||||
/// <summary>
|
||||
/// 复制结果信息
|
||||
/// <see cref="Model.Tag.CopyObject"/>
|
||||
/// </summary>
|
||||
public CopyObject copyObject;
|
||||
|
||||
internal override void ParseResponseBody(System.IO.Stream inputStream, string contentType, long contentLength)
|
||||
{
|
||||
copyObject = new CopyObject();
|
||||
XmlParse.ParseCopyObjectResult(inputStream, copyObject);
|
||||
}
|
||||
|
||||
public override string GetResultInfo()
|
||||
{
|
||||
return base.GetResultInfo() + (copyObject == null ? "" : "\n" + copyObject.GetInfo());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
123
COSXML/Model/Object/DeleteMultiObjectRequest.cs
Normal file
123
COSXML/Model/Object/DeleteMultiObjectRequest.cs
Normal file
@@ -0,0 +1,123 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using System.Text;
|
||||
using COSXML.Model.Tag;
|
||||
using COSXML.Common;
|
||||
using COSXML.Network;
|
||||
using COSXML.CosException;
|
||||
|
||||
namespace COSXML.Model.Object
|
||||
{
|
||||
/// <summary>
|
||||
/// 实现在指定 Bucket 中批量删除 Object,单次请求最大支持批量删除 1000 个 Object
|
||||
/// <see cref="https://cloud.tencent.com/document/product/436/8289"/>
|
||||
/// </summary>
|
||||
public sealed class DeleteMultiObjectRequest : ObjectRequest
|
||||
{
|
||||
/// <summary>
|
||||
/// 删除对象
|
||||
/// <see cref="Model.Tag.Delete"/>
|
||||
/// </summary>
|
||||
private Delete delete;
|
||||
|
||||
public DeleteMultiObjectRequest(string bucket)
|
||||
: base(bucket, "/")
|
||||
{
|
||||
this.method = CosRequestMethod.POST;
|
||||
this.needMD5 = true;
|
||||
this.queryParameters.Add("delete", null);
|
||||
delete = new Delete();
|
||||
delete.deleteObjects = new List<Delete.DeleteObject>();
|
||||
}
|
||||
|
||||
public override void SetCosPath(string key)
|
||||
{
|
||||
// do nothing for delete multi objects api
|
||||
}
|
||||
/// <summary>
|
||||
/// 返回模式
|
||||
/// verbose 模式和 quiet 模式,默认为 verbose 模式。
|
||||
/// verbose 模式返回每个 key 的删除情况,quiet 模式只返回删除失败的 key 的情况;
|
||||
/// </summary>
|
||||
/// <param name="quiet"></param>
|
||||
public void SetDeleteQuiet(bool quiet)
|
||||
{
|
||||
delete.quiet = quiet;
|
||||
}
|
||||
/// <summary>
|
||||
/// 删除对象
|
||||
/// </summary>
|
||||
/// <param name="key"></param>
|
||||
public void SetDeleteKey(string key)
|
||||
{
|
||||
SetDeleteKey(key, null);
|
||||
}
|
||||
/// <summary>
|
||||
/// 删除指定版本的对象
|
||||
/// </summary>
|
||||
/// <param name="key"></param>
|
||||
/// <param name="versionId"></param>
|
||||
public void SetDeleteKey(string key, string versionId)
|
||||
{
|
||||
if (!String.IsNullOrEmpty(key))
|
||||
{
|
||||
if (key.StartsWith("/"))
|
||||
{
|
||||
key = key.Substring(1);
|
||||
}
|
||||
Delete.DeleteObject deleteObject = new Delete.DeleteObject();
|
||||
deleteObject.key = key;
|
||||
if (versionId != null)
|
||||
{
|
||||
deleteObject.versionId = versionId;
|
||||
}
|
||||
delete.deleteObjects.Add(deleteObject);
|
||||
}
|
||||
|
||||
}
|
||||
/// <summary>
|
||||
/// 删除对象
|
||||
/// </summary>
|
||||
/// <param name="keys"></param>
|
||||
public void SetObjectKeys(List<string> keys)
|
||||
{
|
||||
if (keys != null)
|
||||
{
|
||||
foreach (string key in keys)
|
||||
{
|
||||
SetDeleteKey(key, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 删除指定版本的对象
|
||||
/// </summary>
|
||||
/// <param name="versionIdAndKey"></param>
|
||||
public void SetObjectKeys(Dictionary<string, string> versionIdAndKey)
|
||||
{
|
||||
if (versionIdAndKey != null)
|
||||
{
|
||||
foreach (KeyValuePair<string, string> pair in versionIdAndKey)
|
||||
{
|
||||
SetDeleteKey(pair.Value, pair.Key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void CheckParameters()
|
||||
{
|
||||
if (delete.deleteObjects.Count == 0) throw new CosClientException((int)CosClientError.INVALID_ARGUMENT, "delete keys(null or empty) is invalid");
|
||||
base.CheckParameters();
|
||||
}
|
||||
|
||||
public override Network.RequestBody GetRequestBody()
|
||||
{
|
||||
string content = Transfer.XmlBuilder.BuildDelete(delete);
|
||||
byte[] data = Encoding.UTF8.GetBytes(content);
|
||||
ByteRequestBody body = new ByteRequestBody(data);
|
||||
return body;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
33
COSXML/Model/Object/DeleteMultiObjectResult.cs
Normal file
33
COSXML/Model/Object/DeleteMultiObjectResult.cs
Normal file
@@ -0,0 +1,33 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using System.Text;
|
||||
using COSXML.Model.Tag;
|
||||
using COSXML.Transfer;
|
||||
|
||||
namespace COSXML.Model.Object
|
||||
{
|
||||
/// <summary>
|
||||
/// 批量删除 Object返回的结果
|
||||
/// <see cref="https://cloud.tencent.com/document/product/436/8289"/>
|
||||
/// </summary>
|
||||
public sealed class DeleteMultiObjectResult : CosResult
|
||||
{
|
||||
/// <summary>
|
||||
/// 本次删除返回结果的方式和目标 Object
|
||||
/// <see cref="Model.Tag.DeleteResult"/>
|
||||
/// </summary>
|
||||
public DeleteResult deleteResult;
|
||||
|
||||
internal override void ParseResponseBody(System.IO.Stream inputStream, string contentType, long contentLength)
|
||||
{
|
||||
deleteResult = new DeleteResult();
|
||||
XmlParse.ParseDeleteResult(inputStream, deleteResult);
|
||||
}
|
||||
|
||||
public override string GetResultInfo()
|
||||
{
|
||||
return base.GetResultInfo() + (deleteResult == null ? "" : deleteResult.GetInfo());
|
||||
}
|
||||
}
|
||||
}
|
||||
32
COSXML/Model/Object/DeleteObjectRequest.cs
Normal file
32
COSXML/Model/Object/DeleteObjectRequest.cs
Normal file
@@ -0,0 +1,32 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using System.Text;
|
||||
using COSXML.Common;
|
||||
|
||||
namespace COSXML.Model.Object
|
||||
{
|
||||
/// <summary>
|
||||
/// 删除对象
|
||||
/// <see cref="https://cloud.tencent.com/document/product/436/7743"/>
|
||||
/// </summary>
|
||||
public sealed class DeleteObjectRequest : ObjectRequest
|
||||
{
|
||||
public DeleteObjectRequest(string bucket, string key)
|
||||
: base(bucket, key)
|
||||
{
|
||||
this.method = CosRequestMethod.DELETE;
|
||||
}
|
||||
/// <summary>
|
||||
/// 删除指定版本的对象
|
||||
/// </summary>
|
||||
/// <param name="versionId"></param>
|
||||
public void SetVersionId(string versionId)
|
||||
{
|
||||
if (versionId != null)
|
||||
{
|
||||
SetQueryParameter(CosRequestHeaderKey.VERSION_ID, versionId);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
15
COSXML/Model/Object/DeleteObjectResult.cs
Normal file
15
COSXML/Model/Object/DeleteObjectResult.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using System.Text;
|
||||
|
||||
namespace COSXML.Model.Object
|
||||
{
|
||||
/// <summary>
|
||||
/// 删除对象返回的结果
|
||||
/// <see cref="https://cloud.tencent.com/document/product/436/7743"/>
|
||||
/// </summary>
|
||||
public sealed class DeleteObjectResult : CosResult
|
||||
{
|
||||
}
|
||||
}
|
||||
22
COSXML/Model/Object/GetObjectACLRequest.cs
Normal file
22
COSXML/Model/Object/GetObjectACLRequest.cs
Normal file
@@ -0,0 +1,22 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using System.Text;
|
||||
using COSXML.Common;
|
||||
|
||||
namespace COSXML.Model.Object
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取某个存储桶下的某个对象的访问权限
|
||||
/// <see cref="https://cloud.tencent.com/document/product/436/7744"/>
|
||||
/// </summary>
|
||||
public sealed class GetObjectACLRequest : ObjectRequest
|
||||
{
|
||||
public GetObjectACLRequest(string bucket, string key)
|
||||
: base(bucket, key)
|
||||
{
|
||||
this.method = CosRequestMethod.GET;
|
||||
this.queryParameters.Add("acl", null);
|
||||
}
|
||||
}
|
||||
}
|
||||
33
COSXML/Model/Object/GetObjectACLResult.cs
Normal file
33
COSXML/Model/Object/GetObjectACLResult.cs
Normal file
@@ -0,0 +1,33 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using System.Text;
|
||||
using COSXML.Model.Tag;
|
||||
using COSXML.Transfer;
|
||||
|
||||
namespace COSXML.Model.Object
|
||||
{
|
||||
/// <summary>
|
||||
/// 获取某个存储桶下的某个对象的访问权限的返回结果
|
||||
/// <see cref="https://cloud.tencent.com/document/product/436/7744"/>
|
||||
/// </summary>
|
||||
public sealed class GetObjectACLResult : CosResult
|
||||
{
|
||||
/// <summary>
|
||||
/// 访问权限信息
|
||||
/// <see cref="Model.Tag.AccessControlPolicy"/>
|
||||
/// </summary>
|
||||
public AccessControlPolicy accessControlPolicy;
|
||||
|
||||
internal override void ParseResponseBody(System.IO.Stream inputStream, string contentType, long contentLength)
|
||||
{
|
||||
accessControlPolicy = new AccessControlPolicy();
|
||||
XmlParse.ParseAccessControlPolicy(inputStream, accessControlPolicy);
|
||||
}
|
||||
|
||||
public override string GetResultInfo()
|
||||
{
|
||||
return base.GetResultInfo() + (accessControlPolicy == null ? "" : "\n" + accessControlPolicy.GetInfo());
|
||||
}
|
||||
}
|
||||
}
|
||||
133
COSXML/Model/Object/GetObjectBytesRequest.cs
Normal file
133
COSXML/Model/Object/GetObjectBytesRequest.cs
Normal file
@@ -0,0 +1,133 @@
|
||||
|
||||
|
||||
using COSXML.Common;
|
||||
using System;
|
||||
|
||||
namespace COSXML.Model.Object
|
||||
{
|
||||
public sealed class GetObjectBytesRequest : ObjectRequest
|
||||
{
|
||||
/// <summary>
|
||||
/// 下载进度回调
|
||||
/// </summary>
|
||||
private COSXML.Callback.OnProgressCallback progressCallback;
|
||||
|
||||
public GetObjectBytesRequest(string bucket, string key) : base(bucket, key)
|
||||
{
|
||||
this.method = CosRequestMethod.GET;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 下载进度回调
|
||||
/// </summary>
|
||||
/// <param name="progressCallback"></param>
|
||||
public void SetCosProgressCallback(COSXML.Callback.OnProgressCallback progressCallback)
|
||||
{
|
||||
this.progressCallback = progressCallback;
|
||||
}
|
||||
|
||||
internal COSXML.Callback.OnProgressCallback GetCosProgressCallback()
|
||||
{
|
||||
return progressCallback;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 下载内容范围
|
||||
/// </summary>
|
||||
/// <param name="start"></param>
|
||||
/// <param name="end"></param>
|
||||
public void SetRange(long start, long end)
|
||||
{
|
||||
if (start < 0) return;
|
||||
if (end < start) end = -1;
|
||||
SetRequestHeader(CosRequestHeaderKey.RANGE, String.Format("bytes={0}-{1}", start,
|
||||
(end == -1 ? "" : end.ToString())));
|
||||
|
||||
}
|
||||
/// <summary>
|
||||
/// 下载内容的起始偏移量
|
||||
/// </summary>
|
||||
/// <param name="start"></param>
|
||||
public void SetRange(long start)
|
||||
{
|
||||
SetRange(start, -1);
|
||||
}
|
||||
/// <summary>
|
||||
/// 下载特定版本的对象
|
||||
/// </summary>
|
||||
/// <param name="versionId"></param>
|
||||
public void SetVersionId(string versionId)
|
||||
{
|
||||
if (versionId != null)
|
||||
{
|
||||
SetQueryParameter(CosRequestHeaderKey.VERSION_ID, versionId);
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 响应头部中的 Content-Type 参数
|
||||
/// </summary>
|
||||
/// <param name="responseContentType"></param>
|
||||
public void SetResponseContentType(string responseContentType)
|
||||
{
|
||||
if (responseContentType != null)
|
||||
{
|
||||
SetQueryParameter(CosRequestHeaderKey.RESPONSE_CONTENT_TYPE, responseContentType);
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 响应头部中的 Content-Language 参数
|
||||
/// </summary>
|
||||
/// <param name="responseContentLanguage"></param>
|
||||
public void SetResponseContentLanguage(string responseContentLanguage)
|
||||
{
|
||||
if (responseContentLanguage != null)
|
||||
{
|
||||
SetQueryParameter(CosRequestHeaderKey.RESPONSE_CONTENT_LANGUAGE, responseContentLanguage);
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 响应头部中的 Cache-Control 参数
|
||||
/// </summary>
|
||||
/// <param name="responseCacheControl"></param>
|
||||
public void SetResponseCacheControl(string responseCacheControl)
|
||||
{
|
||||
if (responseCacheControl != null)
|
||||
{
|
||||
SetQueryParameter(CosRequestHeaderKey.RESPONSE_CACHE_CONTROL, responseCacheControl);
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 响应头部中的 Content-Disposition 参数
|
||||
/// </summary>
|
||||
/// <param name="responseDisposition"></param>
|
||||
public void SetResponseContentDisposition(string responseDisposition)
|
||||
{
|
||||
if (responseDisposition != null)
|
||||
{
|
||||
SetQueryParameter(CosRequestHeaderKey.RESPONSE_CONTENT_DISPOSITION, responseDisposition);
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 响应头部中的 Content-Encoding 参数
|
||||
/// </summary>
|
||||
/// <param name="responseContentEncoding"></param>
|
||||
public void SetResponseContentEncoding(string responseContentEncoding)
|
||||
{
|
||||
if (responseContentEncoding != null)
|
||||
{
|
||||
SetQueryParameter(CosRequestHeaderKey.RESPONSE_CONTENT_ENCODING, responseContentEncoding);
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 响应头部中的 Content-Expires 参数
|
||||
/// </summary>
|
||||
/// <param name="responseExpires"></param>
|
||||
public void SetResponseExpires(string responseExpires)
|
||||
{
|
||||
if (responseExpires != null)
|
||||
{
|
||||
SetQueryParameter(CosRequestHeaderKey.RESPONSE_EXPIRES, responseExpires);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
59
COSXML/Model/Object/GetObjectBytesResult.cs
Normal file
59
COSXML/Model/Object/GetObjectBytesResult.cs
Normal file
@@ -0,0 +1,59 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
namespace COSXML.Model.Object
|
||||
{
|
||||
public sealed class GetObjectBytesResult : CosResult
|
||||
{
|
||||
public string eTag;
|
||||
|
||||
public byte[] content;
|
||||
|
||||
private COSXML.Callback.OnProgressCallback progressCallback;
|
||||
|
||||
|
||||
internal override void ExternInfo(CosRequest cosRequest)
|
||||
{
|
||||
GetObjectBytesRequest getObjectBytesRequest = cosRequest as GetObjectBytesRequest;
|
||||
this.progressCallback = getObjectBytesRequest.GetCosProgressCallback();
|
||||
}
|
||||
|
||||
internal override void InternalParseResponseHeaders()
|
||||
{
|
||||
List<string> values;
|
||||
this.responseHeaders.TryGetValue("ETag", out values);
|
||||
if (values != null && values.Count > 0)
|
||||
{
|
||||
eTag = values[0];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
internal override void ParseResponseBody(Stream inputStream, string contentType, long contentLength)
|
||||
{
|
||||
content = new byte[contentLength];
|
||||
int completed = 0;
|
||||
while (completed < contentLength)
|
||||
{
|
||||
int recvLen = inputStream.Read(content, completed, (int) Math.Min(2048, contentLength - completed));
|
||||
completed += recvLen;
|
||||
if (progressCallback != null)
|
||||
{
|
||||
progressCallback(completed, content.Length);
|
||||
}
|
||||
}
|
||||
// Unity 上不支持
|
||||
// using(var memoryStream = new MemoryStream())
|
||||
// {
|
||||
// inputStream.CopyTo(memoryStream);
|
||||
// content = memoryStream.ToArray();
|
||||
// }
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
206
COSXML/Model/Object/GetObjectRequest.cs
Normal file
206
COSXML/Model/Object/GetObjectRequest.cs
Normal file
@@ -0,0 +1,206 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using System.Text;
|
||||
using COSXML.Common;
|
||||
using COSXML.CosException;
|
||||
using System.IO;
|
||||
|
||||
namespace COSXML.Model.Object
|
||||
{
|
||||
/// <summary>
|
||||
/// 下载对象
|
||||
/// <see cref="https://cloud.tencent.com/document/product/436/7753"/>
|
||||
/// </summary>
|
||||
public sealed class GetObjectRequest : ObjectRequest
|
||||
{
|
||||
/// <summary>
|
||||
/// 保存文件的本地文件夹路径
|
||||
/// </summary>
|
||||
private string localDir;
|
||||
/// <summary>
|
||||
/// 保存文件的本地的文件名
|
||||
/// </summary>
|
||||
private string localFileName;
|
||||
/// <summary>
|
||||
/// 保存文件的本地偏移位置,下载的数据从此处开始append该文件后面
|
||||
/// </summary>
|
||||
private long localFileOffset = 0;
|
||||
/// <summary>
|
||||
/// 下载进度回调
|
||||
/// </summary>
|
||||
private COSXML.Callback.OnProgressCallback progressCallback;
|
||||
|
||||
|
||||
public GetObjectRequest(string bucket, string key, string localDir, string localFileName)
|
||||
: base(bucket, key)
|
||||
{
|
||||
this.method = CosRequestMethod.GET;
|
||||
this.localDir = localDir;
|
||||
this.localFileName = localFileName;
|
||||
}
|
||||
/// <summary>
|
||||
/// 下载进度回调
|
||||
/// </summary>
|
||||
/// <param name="progressCallback"></param>
|
||||
public void SetCosProgressCallback(COSXML.Callback.OnProgressCallback progressCallback)
|
||||
{
|
||||
this.progressCallback = progressCallback;
|
||||
}
|
||||
|
||||
internal COSXML.Callback.OnProgressCallback GetCosProgressCallback()
|
||||
{
|
||||
return progressCallback;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 保存文件的本地偏移位置,下载的数据从此处开始append该文件后面
|
||||
/// </summary>
|
||||
/// <param name="localFileOffset"></param>
|
||||
public void SetLocalFileOffset(long localFileOffset)
|
||||
{
|
||||
this.localFileOffset = localFileOffset > 0 ? localFileOffset : 0;
|
||||
}
|
||||
|
||||
public long GetLocalFileOffset()
|
||||
{
|
||||
return localFileOffset;
|
||||
}
|
||||
/// <summary>
|
||||
/// 下载内容范围
|
||||
/// </summary>
|
||||
/// <param name="start"></param>
|
||||
/// <param name="end"></param>
|
||||
public void SetRange(long start, long end)
|
||||
{
|
||||
if (start < 0) return;
|
||||
if (end < start) end = -1;
|
||||
SetRequestHeader(CosRequestHeaderKey.RANGE, String.Format("bytes={0}-{1}", start,
|
||||
(end == -1 ? "" : end.ToString())));
|
||||
|
||||
}
|
||||
/// <summary>
|
||||
/// 下载内容的起始偏移量
|
||||
/// </summary>
|
||||
/// <param name="start"></param>
|
||||
public void SetRange(long start)
|
||||
{
|
||||
SetRange(start, -1);
|
||||
}
|
||||
/// <summary>
|
||||
/// 最大下载速度,单位是 bit/s
|
||||
/// </summary>
|
||||
/// <param name="start"></param>
|
||||
public void LimitTraffic(long rate) {
|
||||
SetRequestHeader(CosRequestHeaderKey.X_COS_TRAFFIC_LIMIT, rate.ToString());
|
||||
}
|
||||
/// <summary>
|
||||
/// 下载特定版本的对象
|
||||
/// </summary>
|
||||
/// <param name="versionId"></param>
|
||||
public void SetVersionId(string versionId)
|
||||
{
|
||||
if (versionId != null)
|
||||
{
|
||||
SetQueryParameter(CosRequestHeaderKey.VERSION_ID, versionId);
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 响应头部中的 Content-Type 参数
|
||||
/// </summary>
|
||||
/// <param name="responseContentType"></param>
|
||||
public void SetResponseContentType(string responseContentType)
|
||||
{
|
||||
if (responseContentType != null)
|
||||
{
|
||||
SetQueryParameter(CosRequestHeaderKey.RESPONSE_CONTENT_TYPE, responseContentType);
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 响应头部中的 Content-Language 参数
|
||||
/// </summary>
|
||||
/// <param name="responseContentLanguage"></param>
|
||||
public void SetResponseContentLanguage(string responseContentLanguage)
|
||||
{
|
||||
if (responseContentLanguage != null)
|
||||
{
|
||||
SetQueryParameter(CosRequestHeaderKey.RESPONSE_CONTENT_LANGUAGE, responseContentLanguage);
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 响应头部中的 Cache-Control 参数
|
||||
/// </summary>
|
||||
/// <param name="responseCacheControl"></param>
|
||||
public void SetResponseCacheControl(string responseCacheControl)
|
||||
{
|
||||
if (responseCacheControl != null)
|
||||
{
|
||||
SetQueryParameter(CosRequestHeaderKey.RESPONSE_CACHE_CONTROL, responseCacheControl);
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 响应头部中的 Content-Disposition 参数
|
||||
/// </summary>
|
||||
/// <param name="responseDisposition"></param>
|
||||
public void SetResponseContentDisposition(string responseDisposition)
|
||||
{
|
||||
if (responseDisposition != null)
|
||||
{
|
||||
SetQueryParameter(CosRequestHeaderKey.RESPONSE_CONTENT_DISPOSITION, responseDisposition);
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 响应头部中的 Content-Encoding 参数
|
||||
/// </summary>
|
||||
/// <param name="responseContentEncoding"></param>
|
||||
public void SetResponseContentEncoding(string responseContentEncoding)
|
||||
{
|
||||
if (responseContentEncoding != null)
|
||||
{
|
||||
SetQueryParameter(CosRequestHeaderKey.RESPONSE_CONTENT_ENCODING, responseContentEncoding);
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 响应头部中的 Content-Expires 参数
|
||||
/// </summary>
|
||||
/// <param name="responseExpires"></param>
|
||||
public void SetResponseExpires(string responseExpires)
|
||||
{
|
||||
if (responseExpires != null)
|
||||
{
|
||||
SetQueryParameter(CosRequestHeaderKey.RESPONSE_EXPIRES, responseExpires);
|
||||
}
|
||||
}
|
||||
|
||||
public override void CheckParameters()
|
||||
{
|
||||
if (localDir == null) throw new CosClientException((int)CosClientError.INVALID_ARGUMENT, "localDir = null");
|
||||
if(requestUrlWithSign != null && localFileName == null) throw new CosClientException((int)CosClientError.INVALID_ARGUMENT, "localFileName = null");
|
||||
base.CheckParameters();
|
||||
}
|
||||
/// <summary>
|
||||
/// 获取本地文件保存路径
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public string GetSaveFilePath()
|
||||
{
|
||||
string result = localDir;
|
||||
DirectoryInfo dirInfo = new DirectoryInfo(localDir);
|
||||
if (!dirInfo.Exists)
|
||||
{
|
||||
dirInfo.Create();
|
||||
}
|
||||
if (String.IsNullOrEmpty(localFileName)) localFileName = path;
|
||||
if (localDir.EndsWith(System.IO.Path.DirectorySeparatorChar.ToString(), StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
result = result + localFileName;
|
||||
}
|
||||
else
|
||||
{
|
||||
result = result + System.IO.Path.DirectorySeparatorChar + localFileName;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
32
COSXML/Model/Object/GetObjectResult.cs
Normal file
32
COSXML/Model/Object/GetObjectResult.cs
Normal file
@@ -0,0 +1,32 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using System.Text;
|
||||
using System.IO;
|
||||
using COSXML.CosException;
|
||||
using COSXML.Common;
|
||||
|
||||
namespace COSXML.Model.Object
|
||||
{
|
||||
/// <summary>
|
||||
/// 下载对象返回的结果
|
||||
/// <see cref="https://cloud.tencent.com/document/product/436/7753"/>
|
||||
/// </summary>
|
||||
public sealed class GetObjectResult : CosResult
|
||||
{
|
||||
/// <summary>
|
||||
/// 对象的 eTag
|
||||
/// </summary>
|
||||
public string eTag;
|
||||
|
||||
internal override void InternalParseResponseHeaders()
|
||||
{
|
||||
List<string> values;
|
||||
this.responseHeaders.TryGetValue("ETag", out values);
|
||||
if (values != null && values.Count > 0)
|
||||
{
|
||||
eTag = values[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
44
COSXML/Model/Object/HeadObjectRequest.cs
Normal file
44
COSXML/Model/Object/HeadObjectRequest.cs
Normal file
@@ -0,0 +1,44 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using System.Text;
|
||||
using COSXML.Common;
|
||||
|
||||
namespace COSXML.Model.Object
|
||||
{
|
||||
/// <summary>
|
||||
/// 检索 对象 的 meta 信息数据
|
||||
/// <see cref="https://cloud.tencent.com/document/product/436/7745"/>
|
||||
/// </summary>
|
||||
public sealed class HeadObjectRequest : ObjectRequest
|
||||
{
|
||||
public HeadObjectRequest(string bucket, string key)
|
||||
: base(bucket, key)
|
||||
{
|
||||
this.method = CosRequestMethod.HEAD;
|
||||
}
|
||||
/// <summary>
|
||||
/// 特定版本的对象
|
||||
/// </summary>
|
||||
/// <param name="versionId"></param>
|
||||
public void SetVersionId(string versionId)
|
||||
{
|
||||
if (versionId != null)
|
||||
{
|
||||
SetQueryParameter(CosRequestHeaderKey.VERSION_ID, versionId);
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 当 Object 在指定时间后被修改,则返回对应 Object 的 meta 信息,否则返回 304
|
||||
/// </summary>
|
||||
/// <param name="ifModifiedSince"></param>
|
||||
public void SetIfModifiedSince(string ifModifiedSince)
|
||||
{
|
||||
if (ifModifiedSince != null)
|
||||
{
|
||||
SetRequestHeader(CosRequestHeaderKey.IF_MODIFIED_SINCE, ifModifiedSince);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
57
COSXML/Model/Object/HeadObjectResult.cs
Normal file
57
COSXML/Model/Object/HeadObjectResult.cs
Normal file
@@ -0,0 +1,57 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using System.Text;
|
||||
|
||||
namespace COSXML.Model.Object
|
||||
{
|
||||
/// <summary>
|
||||
/// 检索对象返回的结果
|
||||
/// <see cref="https://cloud.tencent.com/document/product/436/7745"/>
|
||||
/// </summary>
|
||||
public sealed class HeadObjectResult : CosResult
|
||||
{
|
||||
/// <summary>
|
||||
/// 用来表示 Object 是否可以被追加上传,枚举值:normal 或者 appendable
|
||||
/// </summary>
|
||||
public string cosObjectType;
|
||||
/// <summary>
|
||||
/// Object 的存储级别,枚举值:STANDARD,STANDARD_IA
|
||||
/// <see cref="Common.CosStorageClass"/>
|
||||
/// </summary>
|
||||
public string cosStorageClass;
|
||||
/// <summary>
|
||||
/// 对象的长度
|
||||
/// </summary>
|
||||
public long size;
|
||||
/// <summary>
|
||||
/// 对象的eTag
|
||||
/// </summary>
|
||||
public string eTag;
|
||||
|
||||
internal override void InternalParseResponseHeaders()
|
||||
{
|
||||
List<string> values;
|
||||
this.responseHeaders.TryGetValue("x-cos-object-type", out values);
|
||||
if (values != null && values.Count > 0)
|
||||
{
|
||||
cosObjectType = values[0];
|
||||
}
|
||||
this.responseHeaders.TryGetValue("x-cos-storage-class", out values);
|
||||
if (values != null && values.Count > 0)
|
||||
{
|
||||
cosStorageClass = values[0];
|
||||
}
|
||||
this.responseHeaders.TryGetValue("Content-Length", out values);
|
||||
if (values != null && values.Count > 0)
|
||||
{
|
||||
long.TryParse(values[0], out size);
|
||||
}
|
||||
this.responseHeaders.TryGetValue("ETag", out values);
|
||||
if (values != null && values.Count > 0)
|
||||
{
|
||||
eTag = values[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
132
COSXML/Model/Object/InitMultipartUploadRequest.cs
Normal file
132
COSXML/Model/Object/InitMultipartUploadRequest.cs
Normal file
@@ -0,0 +1,132 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using System.Text;
|
||||
using COSXML.Common;
|
||||
using COSXML.Utils;
|
||||
using COSXML.Model.Tag;
|
||||
|
||||
namespace COSXML.Model.Object
|
||||
{
|
||||
/// <summary>
|
||||
/// 实现初始化分片上传,成功执行此请求以后会返回 UploadId 用于后续的 Upload Part 请求
|
||||
/// <see cref="https://cloud.tencent.com/document/product/436/7746"/>
|
||||
/// </summary>
|
||||
public sealed class InitMultipartUploadRequest : ObjectRequest
|
||||
{
|
||||
public InitMultipartUploadRequest(string bucket, string key)
|
||||
: base(bucket, key)
|
||||
{
|
||||
this.method = CosRequestMethod.POST;
|
||||
this.queryParameters.Add("uploads", null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 定义的缓存策略,将作为 Object 元数据保存
|
||||
/// </summary>
|
||||
/// <param name="cacheControl"></param>
|
||||
public void SetCacheControl(string cacheControl)
|
||||
{
|
||||
if (cacheControl != null)
|
||||
{
|
||||
SetRequestHeader(CosRequestHeaderKey.CACHE_CONTROL, cacheControl);
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 定义的文件名称,将作为 Object 元数据保存
|
||||
/// </summary>
|
||||
/// <param name="contentDisposition"></param>
|
||||
public void SetContentDisposition(string contentDisposition)
|
||||
{
|
||||
if (contentDisposition != null)
|
||||
{
|
||||
SetRequestHeader(CosRequestHeaderKey.CONTENT_DISPOSITION, contentDisposition);
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 定义的编码格式,将作为 Object 元数据保存
|
||||
/// </summary>
|
||||
/// <param name="contentEncoding"></param>
|
||||
public void SetContentEncoding(string contentEncoding)
|
||||
{
|
||||
if (contentEncoding != null)
|
||||
{
|
||||
SetRequestHeader(CosRequestHeaderKey.CONTENT_ENCODING, contentEncoding);
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 定义的内容类型(MIME),将作为 Object 元数据保存
|
||||
/// </summary>
|
||||
/// <param name="expires"></param>
|
||||
public void SetExpires(string expires)
|
||||
{
|
||||
if (expires != null)
|
||||
{
|
||||
SetRequestHeader(CosRequestHeaderKey.EXPIRES, expires);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Object 的 ACL 属性,有效值:private,public-read-write,public-read,
|
||||
/// default;默认值:default(继承 Bucket 权限)
|
||||
/// 当前访问策略条目限制为 1000 条,
|
||||
/// 如果您不需要进行 Object ACL 控制,请填 default 或者此项不进行设置,
|
||||
/// 默认继承 Bucket 权限
|
||||
/// <see cref="Common.CosACL"/>
|
||||
/// </summary>
|
||||
/// <param name="cosACL"></param>
|
||||
public void SetCosACL(string cosACL)
|
||||
{
|
||||
if (cosACL != null)
|
||||
{
|
||||
SetRequestHeader(CosRequestHeaderKey.X_COS_ACL, cosACL);
|
||||
}
|
||||
}
|
||||
/// Object 的 ACL 属性,有效值:private,public-read-write,public-read,
|
||||
/// default;默认值:default(继承 Bucket 权限)
|
||||
/// 当前访问策略条目限制为 1000 条,
|
||||
/// 如果您不需要进行 Object ACL 控制,请填 default 或者此项不进行设置,
|
||||
/// 默认继承 Bucket 权限
|
||||
/// <see cref="Common.CosACL"/>
|
||||
public void SetCosACL(CosACL cosACL)
|
||||
{
|
||||
SetRequestHeader(CosRequestHeaderKey.X_COS_ACL, EnumUtils.GetValue(cosACL));
|
||||
}
|
||||
/// <summary>
|
||||
/// 赋予被授权者读的权限
|
||||
/// <see cref="Model.Tag.GrantAccount"/>
|
||||
/// </summary>
|
||||
/// <param name="grantAccount"></param>
|
||||
public void SetXCosGrantRead(GrantAccount grantAccount)
|
||||
{
|
||||
if (grantAccount != null)
|
||||
{
|
||||
SetRequestHeader(CosRequestHeaderKey.X_COS_GRANT_READ, grantAccount.GetGrantAccounts());
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 赋予被授权者写的权限
|
||||
/// <see cref="Model.Tag.GrantAccount"/>
|
||||
/// </summary>
|
||||
/// <param name="grantAccount"></param>
|
||||
public void SetXCosGrantWrite(GrantAccount grantAccount)
|
||||
{
|
||||
if (grantAccount != null)
|
||||
{
|
||||
SetRequestHeader(CosRequestHeaderKey.X_COS_GRANT_WRITE, grantAccount.GetGrantAccounts());
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 赋予被授权者读写的权限
|
||||
/// <see cref="Model.Tag.GrantAccount"/>
|
||||
/// </summary>
|
||||
/// <param name="grantAccount"></param>
|
||||
public void SetXCosReadWrite(GrantAccount grantAccount)
|
||||
{
|
||||
if (grantAccount != null)
|
||||
{
|
||||
SetRequestHeader(CosRequestHeaderKey.X_COS_GRANT_FULL_CONTROL, grantAccount.GetGrantAccounts());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
33
COSXML/Model/Object/InitMultipartUploadResult.cs
Normal file
33
COSXML/Model/Object/InitMultipartUploadResult.cs
Normal file
@@ -0,0 +1,33 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using System.Text;
|
||||
using COSXML.Model.Tag;
|
||||
using COSXML.Transfer;
|
||||
|
||||
namespace COSXML.Model.Object
|
||||
{
|
||||
/// <summary>
|
||||
/// 实现初始化分片上传返回的结果
|
||||
/// <see cref="https://cloud.tencent.com/document/product/436/7746"/>
|
||||
/// </summary>
|
||||
public sealed class InitMultipartUploadResult : CosResult
|
||||
{
|
||||
/// <summary>
|
||||
/// 返回信息
|
||||
/// <see cref="Model.Tag.InitiateMultipartUpload"/>
|
||||
/// </summary>
|
||||
public InitiateMultipartUpload initMultipartUpload;
|
||||
|
||||
internal override void ParseResponseBody(System.IO.Stream inputStream, string contentType, long contentLength)
|
||||
{
|
||||
initMultipartUpload = new InitiateMultipartUpload();
|
||||
XmlParse.ParseInitiateMultipartUpload(inputStream, initMultipartUpload);
|
||||
}
|
||||
|
||||
public override string GetResultInfo()
|
||||
{
|
||||
return base.GetResultInfo() + (initMultipartUpload == null ? "" : "\n" + initMultipartUpload.GetInfo());
|
||||
}
|
||||
}
|
||||
}
|
||||
82
COSXML/Model/Object/ListPartsRequest.cs
Normal file
82
COSXML/Model/Object/ListPartsRequest.cs
Normal file
@@ -0,0 +1,82 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using System.Text;
|
||||
using COSXML.Common;
|
||||
using COSXML.CosException;
|
||||
|
||||
namespace COSXML.Model.Object
|
||||
{
|
||||
/// <summary>
|
||||
/// 查询特定分块上传中的已上传的块
|
||||
/// <see cref="https://cloud.tencent.com/document/product/436/7747"/>
|
||||
/// </summary>
|
||||
public sealed class ListPartsRequest : ObjectRequest
|
||||
{
|
||||
/// <summary>
|
||||
/// 标识本次分块上传的 ID
|
||||
/// </summary>
|
||||
private string uploadId;
|
||||
|
||||
public ListPartsRequest(string bucket, string key, string uploadId)
|
||||
: base(bucket, key)
|
||||
{
|
||||
this.method = CosRequestMethod.GET;
|
||||
this.uploadId = uploadId;
|
||||
}
|
||||
|
||||
public void SetUploadId(string uploadId)
|
||||
{
|
||||
this.uploadId = uploadId;
|
||||
}
|
||||
/// <summary>
|
||||
/// 单次返回最大的条目数量,默认 1000
|
||||
/// </summary>
|
||||
/// <param name="maxParts"></param>
|
||||
public void SetMaxParts(int maxParts)
|
||||
{
|
||||
SetQueryParameter(CosRequestHeaderKey.MAX_PARTS, maxParts.ToString());
|
||||
}
|
||||
/// <summary>
|
||||
/// 默认以 UTF-8 二进制顺序列出条目,所有列出条目从 marker 开始
|
||||
/// </summary>
|
||||
/// <param name="partNumberMarker"></param>
|
||||
public void SetPartNumberMarker(int partNumberMarker)
|
||||
{
|
||||
SetQueryParameter(CosRequestHeaderKey.PART_NUMBER_MARKER, partNumberMarker.ToString());
|
||||
}
|
||||
/// <summary>
|
||||
/// 规定返回值的编码方式
|
||||
/// </summary>
|
||||
/// <param name="encodingType"></param>
|
||||
public void SetEncodingType(string encodingType)
|
||||
{
|
||||
SetQueryParameter(CosRequestHeaderKey.ENCODING_TYPE, encodingType);
|
||||
}
|
||||
|
||||
public override void CheckParameters()
|
||||
{
|
||||
if (requestUrlWithSign != null) return;
|
||||
base.CheckParameters();
|
||||
if (uploadId == null)
|
||||
{
|
||||
throw new CosClientException((int)CosClientError.INVALID_ARGUMENT, "uploadId = null");
|
||||
}
|
||||
}
|
||||
|
||||
protected override void InternalUpdateQueryParameters()
|
||||
{
|
||||
try
|
||||
{
|
||||
queryParameters.Add("uploadId", uploadId);
|
||||
}
|
||||
catch (ArgumentException)
|
||||
{
|
||||
queryParameters["uploadId"] = uploadId;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
34
COSXML/Model/Object/ListPartsResult.cs
Normal file
34
COSXML/Model/Object/ListPartsResult.cs
Normal file
@@ -0,0 +1,34 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using System.Text;
|
||||
using COSXML.Model.Tag;
|
||||
using COSXML.Transfer;
|
||||
|
||||
namespace COSXML.Model.Object
|
||||
{
|
||||
/// <summary>
|
||||
/// 查询特定分块上传中的已上传的块返回的结果
|
||||
/// <see cref="https://cloud.tencent.com/document/product/436/7747"/>
|
||||
/// </summary>
|
||||
public sealed class ListPartsResult : CosResult
|
||||
{
|
||||
/// <summary>
|
||||
/// 已上传块的所有信息
|
||||
/// <see cref="Model.Tag.ListParts"/>
|
||||
/// </summary>
|
||||
public ListParts listParts;
|
||||
|
||||
internal override void ParseResponseBody(System.IO.Stream inputStream, string contentType, long contentLength)
|
||||
{
|
||||
listParts = new ListParts();
|
||||
XmlParse.ParseListParts(inputStream, listParts);
|
||||
}
|
||||
|
||||
public override string GetResultInfo()
|
||||
{
|
||||
return base.GetResultInfo() + (listParts == null ? "" : "\n" + listParts.GetInfo());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
191
COSXML/Model/Object/ObjectRequest.cs
Normal file
191
COSXML/Model/Object/ObjectRequest.cs
Normal file
@@ -0,0 +1,191 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using System.Text;
|
||||
using COSXML.CosException;
|
||||
using COSXML.Common;
|
||||
using COSXML.Utils;
|
||||
|
||||
namespace COSXML.Model.Object
|
||||
{
|
||||
public abstract class ObjectRequest : CosRequest
|
||||
{
|
||||
/// <summary>
|
||||
/// 存储桶名称(Bucket)
|
||||
/// <see cref="https://cloud.tencent.com/document/product/436/7751"/>
|
||||
/// </summary>
|
||||
protected string bucket;
|
||||
|
||||
/// <summary>
|
||||
/// Bucket 所在的地域
|
||||
/// <see cref="Common.CosRegion"/>
|
||||
/// </summary>
|
||||
protected string region;
|
||||
|
||||
public ObjectRequest(string bucket, string key)
|
||||
{
|
||||
this.bucket = bucket;
|
||||
if (!String.IsNullOrEmpty(key) && !key.StartsWith("/"))
|
||||
{
|
||||
this.path = "/" + key;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.path = key;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Object 所属的 Bucket
|
||||
/// </summary>
|
||||
public string Bucket
|
||||
{
|
||||
get { return this.bucket; }
|
||||
set { this.bucket = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Bucket 所在的地域
|
||||
/// <see cref="Common.CosRegion"/>
|
||||
/// </summary>
|
||||
public string Region
|
||||
{
|
||||
get { return this.region; }
|
||||
set { this.region = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// object 名称,对象键
|
||||
/// </summary>
|
||||
/// <param name="key"></param>
|
||||
public virtual void SetCosPath(string key)
|
||||
{
|
||||
if (key != null && !key.StartsWith("/"))
|
||||
{
|
||||
this.path = "/" + key;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.path = key;
|
||||
}
|
||||
}
|
||||
|
||||
public override Network.RequestBody GetRequestBody()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public override string GetCOSHost() {
|
||||
StringBuilder hostBuilder = new StringBuilder();
|
||||
hostBuilder.Append(bucket);
|
||||
if (!String.IsNullOrEmpty(appid) && !bucket.EndsWith("-" + appid))
|
||||
{
|
||||
hostBuilder.Append("-")
|
||||
.Append(appid);
|
||||
}
|
||||
hostBuilder.Append(".cos.")
|
||||
.Append(region)
|
||||
.Append(".myqcloud.com");
|
||||
return hostBuilder.ToString();
|
||||
}
|
||||
|
||||
public override string GetHost()
|
||||
{
|
||||
StringBuilder hostBuilder = new StringBuilder();
|
||||
if (!String.IsNullOrEmpty(serviceConfig.host)) {
|
||||
hostBuilder.Append(serviceConfig.host);
|
||||
} else {
|
||||
hostBuilder.Append(bucket);
|
||||
if (!String.IsNullOrEmpty(appid) && !bucket.EndsWith("-" + appid))
|
||||
{
|
||||
hostBuilder.Append("-")
|
||||
.Append(appid);
|
||||
}
|
||||
if (serviceConfig.endpointSuffix != null) {
|
||||
hostBuilder.Append(".")
|
||||
.Append(serviceConfig.endpointSuffix);
|
||||
} else {
|
||||
hostBuilder.Append(".cos.")
|
||||
.Append(region)
|
||||
.Append(".myqcloud.com");
|
||||
}
|
||||
}
|
||||
return hostBuilder.ToString();
|
||||
}
|
||||
|
||||
public override void CheckParameters()
|
||||
{
|
||||
if (requestUrlWithSign != null) return;
|
||||
//if (appid == null)
|
||||
//{
|
||||
// throw new CosClientException((int)CosClientError.INVALID_ARGUMENT, "appid is null");
|
||||
//}
|
||||
if (bucket == null || bucket.Length < 1)
|
||||
{
|
||||
throw new CosClientException((int)CosClientError.INVALID_ARGUMENT, "bucket is null");
|
||||
}
|
||||
// if (region == null || region.Length < 1)
|
||||
// {
|
||||
// throw new CosClientException((int)CosClientError.INVALID_ARGUMENT, "region is null");
|
||||
// }
|
||||
if (path == null || path.Length < 1)
|
||||
{
|
||||
throw new CosClientException((int)CosClientError.INVALID_ARGUMENT, "cosPath(null or empty)is invalid");
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void InternalUpdateQueryParameters()
|
||||
{
|
||||
}
|
||||
|
||||
protected virtual void InteranlUpdateHeaders() { }
|
||||
|
||||
public override Dictionary<string, string> GetRequestParamters()
|
||||
{
|
||||
InternalUpdateQueryParameters();
|
||||
return base.GetRequestParamters();
|
||||
}
|
||||
|
||||
public override Dictionary<string, string> GetRequestHeaders()
|
||||
{
|
||||
InteranlUpdateHeaders();
|
||||
return base.GetRequestHeaders();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// cos 服务端加密
|
||||
/// </summary>
|
||||
public void SetCosServerSideEncryption()
|
||||
{
|
||||
SetRequestHeader("x-cos-server-side-encryption", "AES256");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="customerKey"></param>
|
||||
public void SetCosServerSideEncryptionWithCustomerKey(string customerKey)
|
||||
{
|
||||
if (customerKey != null)
|
||||
{
|
||||
SetRequestHeader("x-cos-server-side-encryption-customer-algorithm", "AES256");
|
||||
SetRequestHeader("x-cos-server-side-encryption-customer-key", DigestUtils.GetBase64(customerKey, Encoding.UTF8));
|
||||
SetRequestHeader("x-cos-server-side-encryption-customer-key-MD5", DigestUtils.GetMd5ToBase64(customerKey, Encoding.UTF8));
|
||||
}
|
||||
}
|
||||
|
||||
public void SetCosServerSideEncryptionWithKMS(string customerKeyID, string json)
|
||||
{
|
||||
SetRequestHeader("x-cos-server-side-encryption", "cos/kms");
|
||||
if (customerKeyID != null)
|
||||
{
|
||||
SetRequestHeader("x-cos-server-side-encryption-cos-kms-key-id", customerKeyID);
|
||||
}
|
||||
if (json != null)
|
||||
{
|
||||
SetRequestHeader("x-cos-server-side-encryption-context", DigestUtils.GetBase64(json, Encoding.UTF8));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
109
COSXML/Model/Object/OptionObjectRequest.cs
Normal file
109
COSXML/Model/Object/OptionObjectRequest.cs
Normal file
@@ -0,0 +1,109 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using System.Text;
|
||||
using COSXML.Common;
|
||||
using COSXML.CosException;
|
||||
|
||||
namespace COSXML.Model.Object
|
||||
{
|
||||
/// <summary>
|
||||
/// 实现 Object 跨域访问配置的预请求
|
||||
/// <see cref="https://cloud.tencent.com/document/product/436/8288"/>
|
||||
/// </summary>
|
||||
public sealed class OptionObjectRequest : ObjectRequest
|
||||
{
|
||||
/// <summary>
|
||||
/// 模拟跨域访问的请求来源域名
|
||||
/// </summary>
|
||||
private string origin;
|
||||
/// <summary>
|
||||
/// 模拟跨域访问的请求 HTTP 方法
|
||||
/// </summary>
|
||||
private string accessControlMethod;
|
||||
|
||||
public OptionObjectRequest(string bucket, string key, string origin, string accessControlMethod)
|
||||
: base(bucket, key)
|
||||
{
|
||||
this.method = CosRequestMethod.OPTIONS;
|
||||
this.origin = origin;
|
||||
if (accessControlMethod != null)
|
||||
{
|
||||
this.accessControlMethod = accessControlMethod.ToUpper();
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 模拟跨域访问的请求来源域名
|
||||
/// </summary>
|
||||
/// <param name="origin"></param>
|
||||
public void SetOrigin(string origin)
|
||||
{
|
||||
this.origin = origin;
|
||||
}
|
||||
/// <summary>
|
||||
/// 模拟跨域访问的请求 HTTP 方法
|
||||
/// </summary>
|
||||
/// <param name="accessControlMethod"></param>
|
||||
public void SetAccessControlMethod(string accessControlMethod)
|
||||
{
|
||||
if (accessControlMethod != null)
|
||||
{
|
||||
this.accessControlMethod = accessControlMethod.ToUpper();
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 模拟跨域访问的请求头部
|
||||
/// </summary>
|
||||
/// <param name="accessControlHeaders"></param>
|
||||
public void SetAccessControlHeaders(List<string> accessControlHeaders)
|
||||
{
|
||||
if (accessControlHeaders != null)
|
||||
{
|
||||
StringBuilder headers = new StringBuilder();
|
||||
foreach (string accessControlHeader in accessControlHeaders)
|
||||
{
|
||||
if(accessControlHeader != null) headers.Append(accessControlHeader).Append(",");
|
||||
}
|
||||
string result = headers.ToString();
|
||||
if (result.EndsWith(","))
|
||||
{
|
||||
result = result.Substring(0, result.Length - 1);
|
||||
SetRequestHeader(CosRequestHeaderKey.ACCESS_CONTROL_REQUEST_HEADERS, result);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void CheckParameters()
|
||||
{
|
||||
if (origin == null)
|
||||
{
|
||||
throw new CosClientException((int)CosClientError.INVALID_ARGUMENT, "origin = null");
|
||||
}
|
||||
if (accessControlMethod == null)
|
||||
{
|
||||
throw new CosClientException((int)CosClientError.INVALID_ARGUMENT, "accessControlMethod = null");
|
||||
}
|
||||
base.CheckParameters();
|
||||
}
|
||||
|
||||
protected override void InteranlUpdateHeaders()
|
||||
{
|
||||
try
|
||||
{
|
||||
this.headers.Add(CosRequestHeaderKey.ORIGIN, origin);
|
||||
}
|
||||
catch (ArgumentException)
|
||||
{
|
||||
this.headers[CosRequestHeaderKey.ORIGIN] = origin;
|
||||
}
|
||||
try
|
||||
{
|
||||
this.headers.Add(CosRequestHeaderKey.ACCESS_CONTROL_REQUEST_METHOD, accessControlMethod);
|
||||
}
|
||||
catch (ArgumentException)
|
||||
{
|
||||
this.headers[CosRequestHeaderKey.ACCESS_CONTROL_REQUEST_METHOD] = accessControlMethod;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
70
COSXML/Model/Object/OptionObjectResult.cs
Normal file
70
COSXML/Model/Object/OptionObjectResult.cs
Normal file
@@ -0,0 +1,70 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using System.Text;
|
||||
|
||||
namespace COSXML.Model.Object
|
||||
{
|
||||
/// <summary>
|
||||
/// 实现 Object 跨域访问配置的预请求
|
||||
/// <see cref="https://cloud.tencent.com/document/product/436/8288"/>
|
||||
/// </summary>
|
||||
public sealed class OptionObjectResult : CosResult
|
||||
{
|
||||
/// <summary>
|
||||
/// 跨域访问的请求来源域名
|
||||
/// </summary>
|
||||
public string accessControlAllowOrigin;
|
||||
/// <summary>
|
||||
/// OPTIONS 请求得到结果的有效期
|
||||
/// </summary>
|
||||
public long accessControlMaxAge;
|
||||
/// <summary>
|
||||
/// 跨域访问的允许请求头部
|
||||
/// </summary>
|
||||
public List<string> accessControlAllowHeaders;
|
||||
/// <summary>
|
||||
/// 跨域访问的允许请求 HTTP 方法
|
||||
/// </summary>
|
||||
public List<string> accessControlAllowMethods;
|
||||
/// <summary>
|
||||
/// 跨域访问的允许请求自定义头部
|
||||
/// </summary>
|
||||
public List<string> accessControlAllowExposeHeaders;
|
||||
|
||||
internal override void InternalParseResponseHeaders()
|
||||
{
|
||||
List<string> values;
|
||||
this.responseHeaders.TryGetValue("Access-Control-Allow-Origin", out values);
|
||||
if (values != null && values.Count > 0)
|
||||
{
|
||||
accessControlAllowOrigin = values[0];
|
||||
}
|
||||
this.responseHeaders.TryGetValue("Access-Control-Max-Age", out values);
|
||||
if (values != null && values.Count > 0)
|
||||
{
|
||||
long.TryParse(values[0], out accessControlMaxAge);
|
||||
}
|
||||
this.responseHeaders.TryGetValue("Access-Control-Allow-Methods", out values);
|
||||
if (values != null && values.Count > 0)
|
||||
{
|
||||
accessControlAllowMethods = new List<string>(values[0].Split(','));
|
||||
}
|
||||
this.responseHeaders.TryGetValue("Access-Control-Allow-Headers", out values);
|
||||
if (values != null && values.Count > 0)
|
||||
{
|
||||
accessControlAllowHeaders = new List<string>(values[0].Split(','));
|
||||
}
|
||||
this.responseHeaders.TryGetValue("Access-Control-Expose-Headers", out values);
|
||||
if (values != null && values.Count > 0)
|
||||
{
|
||||
accessControlAllowExposeHeaders = new List<string>(values[0].Split(','));
|
||||
}
|
||||
}
|
||||
|
||||
public override string GetResultInfo()
|
||||
{
|
||||
return base.GetResultInfo() + "\n" + accessControlAllowOrigin;
|
||||
}
|
||||
}
|
||||
}
|
||||
450
COSXML/Model/Object/PostObjectRequest.cs
Normal file
450
COSXML/Model/Object/PostObjectRequest.cs
Normal file
@@ -0,0 +1,450 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using System.Text;
|
||||
using COSXML.Common;
|
||||
using System.IO;
|
||||
using COSXML.Utils;
|
||||
using COSXML.CosException;
|
||||
using COSXML.Auth;
|
||||
using COSXML.Log;
|
||||
using COSXML.Network;
|
||||
|
||||
namespace COSXML.Model.Object
|
||||
{
|
||||
/// <summary>
|
||||
/// 使用者用表单的形式将文件(Object)上传至指定 Bucket 中.
|
||||
/// <see cref="https://cloud.tencent.com/document/product/436/14690"/>
|
||||
/// </summary>
|
||||
public sealed class PostObjectRequest : ObjectRequest
|
||||
{
|
||||
private static string TAG = typeof(PostObjectRequest).FullName;
|
||||
/// <summary>
|
||||
/// 表单字段
|
||||
/// <see cref="FormStruct"/>
|
||||
/// </summary>
|
||||
private FormStruct formStruct;
|
||||
|
||||
private PostObjectRequest(string bucket, string key)
|
||||
: base(bucket, "/")
|
||||
{
|
||||
this.method = CosRequestMethod.POST;
|
||||
formStruct = new FormStruct();
|
||||
formStruct.key = key;
|
||||
this.headers.Add(CosRequestHeaderKey.CONTENT_TYPE, "multipart/form-data; boundary=" + MultipartRequestBody.BOUNDARY);
|
||||
this.needMD5 = false;
|
||||
}
|
||||
/// <summary>
|
||||
/// 上传文件
|
||||
/// </summary>
|
||||
/// <param name="bucket"></param>
|
||||
/// <param name="key"></param>
|
||||
/// <param name="srcPath"></param>
|
||||
public PostObjectRequest(string bucket, string key, string srcPath)
|
||||
:this(bucket, key, srcPath, -1L, -1L)
|
||||
{
|
||||
}
|
||||
/// <summary>
|
||||
/// 上传文件的指定部分
|
||||
/// </summary>
|
||||
/// <param name="bucket"></param>
|
||||
/// <param name="key"></param>
|
||||
/// <param name="srcPath"></param>
|
||||
/// <param name="fileOffset">指定文件内容的起始位置</param>
|
||||
/// <param name="sendContentLength">指定文件内容的大小</param>
|
||||
public PostObjectRequest(string bucket, string key, string srcPath, long fileOffset, long sendContentLength)
|
||||
: this(bucket, key)
|
||||
{
|
||||
formStruct.srcPath = srcPath;
|
||||
formStruct.fileOffset = fileOffset < 0 ? 0 : fileOffset;
|
||||
formStruct.contentLength = sendContentLength < 0L ? -1L : sendContentLength;
|
||||
}
|
||||
/// <summary>
|
||||
/// 上传data数据
|
||||
/// </summary>
|
||||
/// <param name="bucket"></param>
|
||||
/// <param name="key"></param>
|
||||
/// <param name="data"></param>
|
||||
public PostObjectRequest(string bucket, string key, byte[] data)
|
||||
:this(bucket, key)
|
||||
{
|
||||
formStruct.data = data;
|
||||
}
|
||||
/// <summary>
|
||||
/// 设置进度回调
|
||||
/// </summary>
|
||||
/// <param name="progressCallback"></param>
|
||||
public void SetCosProgressCallback(COSXML.Callback.OnProgressCallback progressCallback)
|
||||
{
|
||||
formStruct.progressCallback = progressCallback;
|
||||
}
|
||||
/// <summary>
|
||||
/// 定义 Object 的 acl 属性。有效值:private,public-read-write,public-read;默认值:private
|
||||
/// <see cref="Common.CosACL"/>
|
||||
/// </summary>
|
||||
/// <param name="cosACL"></param>
|
||||
public void SetCosACL(CosACL cosACL)
|
||||
{
|
||||
formStruct.acl = EnumUtils.GetValue(cosACL);
|
||||
}
|
||||
/// <summary>
|
||||
/// 设置对象的 cacheControl
|
||||
/// </summary>
|
||||
/// <param name="cacheControl"></param>
|
||||
public void SetCacheControl(string cacheControl)
|
||||
{
|
||||
SetHeader("Cache-Control", cacheControl);
|
||||
}
|
||||
/// <summary>
|
||||
/// 设置对象的contentType
|
||||
/// </summary>
|
||||
/// <param name="contentType"></param>
|
||||
public void SetContentType(string contentType)
|
||||
{
|
||||
SetHeader("Content-Type", contentType);
|
||||
}
|
||||
/// <summary>
|
||||
/// 设置对象的contentDisposition
|
||||
/// </summary>
|
||||
/// <param name="contentDisposition"></param>
|
||||
public void SetContentDisposition(string contentDisposition)
|
||||
{
|
||||
SetHeader("Content-Disposition", contentDisposition);
|
||||
}
|
||||
/// <summary>
|
||||
/// 设置对象的contentEncoding
|
||||
/// </summary>
|
||||
/// <param name="contentEncoding"></param>
|
||||
public void SetContentEncoding(string contentEncoding)
|
||||
{
|
||||
SetHeader("Content-Encoding", contentEncoding);
|
||||
}
|
||||
/// <summary>
|
||||
/// 设置对象 Expire
|
||||
/// </summary>
|
||||
/// <param name="expires"></param>
|
||||
public void SetExpires(string expires)
|
||||
{
|
||||
SetHeader("Expires", expires);
|
||||
}
|
||||
/// <summary>
|
||||
/// 设置对象header属性
|
||||
/// </summary>
|
||||
/// <param name="key"></param>
|
||||
/// <param name="value"></param>
|
||||
public void SetHeader(string key, string value)
|
||||
{
|
||||
try
|
||||
{
|
||||
formStruct.headers.Add(key, value);
|
||||
}
|
||||
catch (ArgumentNullException)
|
||||
{
|
||||
QLog.D(TAG, "SetHeader: key ==null");
|
||||
}
|
||||
catch (ArgumentException)
|
||||
{
|
||||
formStruct.headers[key] = value;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 设置对象自定义的header属性
|
||||
/// </summary>
|
||||
/// <param name="key"></param>
|
||||
/// <param name="value"></param>
|
||||
public void SetCustomerHeader(string key, string value)
|
||||
{
|
||||
try
|
||||
{
|
||||
formStruct.customHeaders.Add(key, value);
|
||||
}
|
||||
catch (ArgumentNullException)
|
||||
{
|
||||
QLog.D(TAG, "SetHeader: key ==null");
|
||||
}
|
||||
catch (ArgumentException)
|
||||
{
|
||||
formStruct.customHeaders[key] = value;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 设置对象的存储类型
|
||||
/// <see cref="Common.CosStorageClass"/>
|
||||
/// </summary>
|
||||
/// <param name="cosStorageClass"></param>
|
||||
public void SetCosStorageClass(string cosStorageClass)
|
||||
{
|
||||
formStruct.xCosStorageClass = cosStorageClass;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 最大上传速度,单位是 bit/s
|
||||
/// </summary>
|
||||
/// <param name="start"></param>
|
||||
public void LimitTraffic(long rate) {
|
||||
formStruct.xCOSTrafficLimit = rate.ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 若设置优先生效,返回 303 并提供 Location 头部,
|
||||
/// 会在 URL 尾部加上 bucket={bucket}&key={key}&etag={%22etag%22} 参数。
|
||||
/// </summary>
|
||||
/// <param name="redirectHost"></param>
|
||||
public void SetSuccessActionRedirect(string redirectHost)
|
||||
{
|
||||
formStruct.successActionRedirect = redirectHost;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// successHttpCode can be 200, 201, 204, default value 204
|
||||
/// 若填写 success_action_redirect 则会略此设置。
|
||||
/// </summary>
|
||||
/// <param name="successHttpCode"></param>
|
||||
public void SetSuccessActionStatus(int successHttpCode)
|
||||
{
|
||||
formStruct.successActionStatus = successHttpCode.ToString();
|
||||
}
|
||||
/// <summary>
|
||||
/// 用于做请求检查,如果请求的内容和 Policy 指定的条件不符,返回 403 AccessDenied。
|
||||
/// <see cref="Policy"/>
|
||||
/// </summary>
|
||||
/// <param name="policy"></param>
|
||||
public void SetPolicy(Policy policy)
|
||||
{
|
||||
formStruct.policy = policy;
|
||||
}
|
||||
|
||||
public override void SetSign(string sign)
|
||||
{
|
||||
formStruct.sign = sign;
|
||||
}
|
||||
|
||||
public override void CheckParameters()
|
||||
{
|
||||
formStruct.CheckParameter();
|
||||
base.CheckParameters();
|
||||
}
|
||||
|
||||
public override CosXmlSignSourceProvider GetSignSourceProvider()
|
||||
{
|
||||
if (this.cosXmlSignSourceProvider != null)
|
||||
{
|
||||
this.cosXmlSignSourceProvider.setSignAll(false);
|
||||
this.cosXmlSignSourceProvider.onGetSign = delegate(Request request, string sign)
|
||||
{
|
||||
//添加参数 sign
|
||||
((MultipartRequestBody)request.Body).AddParameter("Signature", sign);
|
||||
};
|
||||
}
|
||||
return base.GetSignSourceProvider();
|
||||
}
|
||||
|
||||
public override RequestBody GetRequestBody()
|
||||
{
|
||||
MultipartRequestBody requestBody = new MultipartRequestBody();
|
||||
requestBody.AddParamters(formStruct.GetFormParameters());
|
||||
if (formStruct.data != null)
|
||||
{
|
||||
requestBody.AddData(formStruct.data, "file", "tmp");
|
||||
}
|
||||
else if (formStruct.srcPath != null)
|
||||
{
|
||||
FileInfo fileInfo = new FileInfo(this.formStruct.srcPath);
|
||||
string fileName = fileInfo.Name;
|
||||
if (formStruct.contentLength == -1L || formStruct.contentLength + formStruct.fileOffset > fileInfo.Length)
|
||||
{
|
||||
formStruct.contentLength = fileInfo.Length - formStruct.fileOffset;
|
||||
}
|
||||
requestBody.AddData(formStruct.srcPath, formStruct.fileOffset, formStruct.contentLength, "file", fileName);
|
||||
}
|
||||
requestBody.ProgressCallback = formStruct.progressCallback;
|
||||
return requestBody;
|
||||
}
|
||||
|
||||
private class FormStruct
|
||||
{
|
||||
/// <summary>
|
||||
/// 对象的ACL
|
||||
/// </summary>
|
||||
public string acl;
|
||||
/// <summary>
|
||||
/// 对象的header元数据
|
||||
/// </summary>
|
||||
public Dictionary<string, string> headers;
|
||||
/// <summary>
|
||||
/// 上传后的文件名,使用 ${filename} 则会进行替换。
|
||||
/// 例如a/b/${filename},上传文件 a1.txt,那么最终的上传路径就是 a/b/a1.txt
|
||||
/// </summary>
|
||||
public string key;
|
||||
/// <summary>
|
||||
/// 若设置优先生效,返回 303 并提供 Location 头部
|
||||
/// </summary>
|
||||
public string successActionRedirect;
|
||||
/// <summary>
|
||||
/// 可选 200,201,204 默认返回 204。若填写 success_action_redirect 则会略此设置。
|
||||
/// </summary>
|
||||
public string successActionStatus;
|
||||
/// <summary>
|
||||
/// 对象的自定义元数据
|
||||
/// </summary>
|
||||
public Dictionary<string, string> customHeaders;
|
||||
/// <summary>
|
||||
/// 对象存储类型
|
||||
/// </summary>
|
||||
public string xCosStorageClass;
|
||||
/// <summary>
|
||||
/// 速度限制
|
||||
/// </summary>
|
||||
public string xCOSTrafficLimit;
|
||||
/// <summary>
|
||||
/// 签名串
|
||||
/// </summary>
|
||||
public string sign;
|
||||
/// <summary>
|
||||
/// 请求检查策略
|
||||
/// <see cref="Policy"/>
|
||||
/// </summary>
|
||||
public Policy policy;
|
||||
/// <summary>
|
||||
/// 上传文件的本地路径
|
||||
/// </summary>
|
||||
public string srcPath;
|
||||
/// <summary>
|
||||
/// 上传文件指定起始位置
|
||||
/// </summary>
|
||||
public long fileOffset = 0L;
|
||||
/// <summary>
|
||||
/// 上传文件指定内容大小
|
||||
/// </summary>
|
||||
public long contentLength = -1L;
|
||||
/// <summary>
|
||||
/// 上传data数据
|
||||
/// </summary>
|
||||
public byte[] data;
|
||||
/// <summary>
|
||||
/// 上传回调
|
||||
/// </summary>
|
||||
public COSXML.Callback.OnProgressCallback progressCallback;
|
||||
|
||||
|
||||
public FormStruct()
|
||||
{
|
||||
headers = new Dictionary<string, string>();
|
||||
customHeaders = new Dictionary<string, string>();
|
||||
}
|
||||
|
||||
public Dictionary<string, string> GetFormParameters()
|
||||
{
|
||||
Dictionary<string, string> formParameters = new Dictionary<string, string>();
|
||||
if(acl != null){
|
||||
formParameters.Add("Acl", acl);
|
||||
}
|
||||
foreach(KeyValuePair<string, string> pair in headers){
|
||||
formParameters.Add(pair.Key, pair.Value);
|
||||
}
|
||||
formParameters.Add("key", key);
|
||||
if(successActionRedirect != null){
|
||||
formParameters.Add("success_action_redirect", successActionRedirect);
|
||||
}
|
||||
if(successActionStatus != null){
|
||||
formParameters.Add("success_action_status", successActionStatus);
|
||||
}
|
||||
foreach(KeyValuePair<string, string> pair in customHeaders){
|
||||
formParameters.Add(pair.Key, pair.Value);
|
||||
}
|
||||
if(xCosStorageClass != null){
|
||||
formParameters.Add("x-cos-storage-class", xCosStorageClass);
|
||||
}
|
||||
if(xCOSTrafficLimit != null) {
|
||||
formParameters.Add(CosRequestHeaderKey.X_COS_TRAFFIC_LIMIT, xCOSTrafficLimit);
|
||||
}
|
||||
if (sign != null)
|
||||
{
|
||||
formParameters.Add("Signature", sign);
|
||||
}
|
||||
if(policy != null){
|
||||
formParameters.Add("policy", DigestUtils.GetBase64(policy.Content(), Encoding.UTF8));
|
||||
}
|
||||
return formParameters;
|
||||
}
|
||||
|
||||
public void CheckParameter()
|
||||
{
|
||||
if (String.IsNullOrEmpty(key)) throw new CosClientException((int)CosClientError.INVALID_ARGUMENT, "FormStruct.key(null or empty) is invalid");
|
||||
if (srcPath == null && data == null)
|
||||
{
|
||||
throw new CosClientException((int)CosClientError.INVALID_ARGUMENT, "data source = null");
|
||||
}
|
||||
if (srcPath != null)
|
||||
{
|
||||
if (!File.Exists(srcPath)) throw new CosClientException((int)CosClientError.INVALID_ARGUMENT, "srcPath not exist");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class Policy
|
||||
{
|
||||
/// <summary>
|
||||
/// 过期时间
|
||||
/// </summary>
|
||||
private string expiration;
|
||||
/// <summary>
|
||||
/// 检查条件
|
||||
/// </summary>
|
||||
private StringBuilder conditions = new StringBuilder();
|
||||
|
||||
public void SetExpiration(long endTimeMills)
|
||||
{
|
||||
this.expiration = TimeUtils.GetFormatTime("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", endTimeMills, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
|
||||
public void SetExpiration(string formatEndTime)
|
||||
{
|
||||
this.expiration = formatEndTime;
|
||||
}
|
||||
|
||||
public void AddConditions(string key, string value, bool isPrefixMatch)
|
||||
{
|
||||
if(isPrefixMatch){
|
||||
conditions.Append('[')
|
||||
.Append("starts-with")
|
||||
.Append(',')
|
||||
.Append(key)
|
||||
.Append(',')
|
||||
.Append(value)
|
||||
.Append(']');
|
||||
}else {
|
||||
conditions.Append('{')
|
||||
.Append(key)
|
||||
.Append(':')
|
||||
.Append(value)
|
||||
.Append('}');
|
||||
}
|
||||
}
|
||||
|
||||
public void AddContentConditions(int start, int end)
|
||||
{
|
||||
conditions.Append('[')
|
||||
.Append("content-length-range")
|
||||
.Append(',')
|
||||
.Append(start)
|
||||
.Append(',')
|
||||
.Append(end)
|
||||
.Append(']');
|
||||
}
|
||||
|
||||
public string Content()
|
||||
{
|
||||
StringBuilder content = new StringBuilder();
|
||||
content.Append('{');
|
||||
if (expiration != null)
|
||||
{
|
||||
content.Append(String.Format("expiration:{0}", expiration));
|
||||
}
|
||||
content.Append(String.Format("conditions:{0}", conditions));
|
||||
content.Append('}');
|
||||
return content.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
58
COSXML/Model/Object/PostObjectResult.cs
Normal file
58
COSXML/Model/Object/PostObjectResult.cs
Normal file
@@ -0,0 +1,58 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using System.Text;
|
||||
using COSXML.Model.Tag;
|
||||
using COSXML.Transfer;
|
||||
|
||||
namespace COSXML.Model.Object
|
||||
{
|
||||
/// <summary>
|
||||
/// 使用者用表单的形式将文件(Object)上传至指定 Bucket 中.
|
||||
/// <see cref="https://cloud.tencent.com/document/product/436/14690"/>
|
||||
/// </summary>
|
||||
public sealed class PostObjectResult : CosResult
|
||||
{
|
||||
/// <summary>
|
||||
/// 对象的eTag
|
||||
/// </summary>
|
||||
public string eTag;
|
||||
/// <summary>
|
||||
/// 若指定了上传 success_action_redirect 则返回对应的值,若无指定则返回对象完整的路径
|
||||
/// </summary>
|
||||
public string location;
|
||||
/// <summary>
|
||||
/// post object返回的信息
|
||||
/// <see cref="Model.Tag.PostResponse"/>
|
||||
/// </summary>
|
||||
public PostResponse postResponse;
|
||||
|
||||
internal override void InternalParseResponseHeaders()
|
||||
{
|
||||
List<string> values;
|
||||
this.responseHeaders.TryGetValue("ETag", out values);
|
||||
if (values != null && values.Count > 0)
|
||||
{
|
||||
eTag = values[0];
|
||||
}
|
||||
this.responseHeaders.TryGetValue("Location", out values);
|
||||
if (values != null && values.Count > 0)
|
||||
{
|
||||
location = values[0];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
internal override void ParseResponseBody(System.IO.Stream inputStream, string contentType, long contentLength)
|
||||
{
|
||||
if (contentLength <= 0) return;
|
||||
postResponse = new PostResponse();
|
||||
XmlParse.ParsePostResponse(inputStream, postResponse);
|
||||
}
|
||||
|
||||
public override string GetResultInfo()
|
||||
{
|
||||
return base.GetResultInfo() + (postResponse == null ? "" : ('\n' + postResponse.GetInfo()));
|
||||
}
|
||||
}
|
||||
}
|
||||
81
COSXML/Model/Object/PutObjectACLRequest.cs
Normal file
81
COSXML/Model/Object/PutObjectACLRequest.cs
Normal file
@@ -0,0 +1,81 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using System.Text;
|
||||
using COSXML.Common;
|
||||
using COSXML.Utils;
|
||||
using COSXML.Model.Tag;
|
||||
|
||||
namespace COSXML.Model.Object
|
||||
{
|
||||
/// <summary>
|
||||
/// 设置 对象 的ACL
|
||||
/// <see cref="https://cloud.tencent.com/document/product/436/7748"/>
|
||||
/// </summary>
|
||||
public sealed class PutObjectACLRequest : ObjectRequest
|
||||
{
|
||||
public PutObjectACLRequest(string bucket, string key)
|
||||
: base(bucket, key)
|
||||
{
|
||||
this.method = CosRequestMethod.PUT;
|
||||
this.queryParameters.Add("acl", null);
|
||||
}
|
||||
/// <summary>
|
||||
/// 定义 Object 的 acl 属性。有效值:private,public-read-write,public-read;默认值:private
|
||||
/// <see cref="Common.CosACL"/>
|
||||
/// </summary>
|
||||
/// <param name="cosACL"></param>
|
||||
public void SetCosACL(string cosACL)
|
||||
{
|
||||
if (cosACL != null)
|
||||
{
|
||||
SetRequestHeader(CosRequestHeaderKey.X_COS_ACL, cosACL);
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 定义 Object 的 acl 属性。有效值:private,public-read-write,public-read;默认值:private
|
||||
/// <see cref="Common.CosACL"/>
|
||||
/// </summary>
|
||||
/// <param name="cosACL"></param>
|
||||
public void SetCosACL(CosACL cosACL)
|
||||
{
|
||||
SetRequestHeader(CosRequestHeaderKey.X_COS_ACL, EnumUtils.GetValue(cosACL));
|
||||
}
|
||||
/// <summary>
|
||||
/// 赋予被授权者读的权限
|
||||
/// <see cref="Model.Tag.GrantAccount"/>
|
||||
/// </summary>
|
||||
/// <param name="grantAccount"></param>
|
||||
public void SetXCosGrantRead(GrantAccount grantAccount)
|
||||
{
|
||||
if (grantAccount != null)
|
||||
{
|
||||
SetRequestHeader(CosRequestHeaderKey.X_COS_GRANT_READ, grantAccount.GetGrantAccounts());
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 赋予被授权者写的权限
|
||||
/// <see cref="Model.Tag.GrantAccount"/>
|
||||
/// </summary>
|
||||
/// <param name="grantAccount"></param>
|
||||
public void SetXCosGrantWrite(GrantAccount grantAccount)
|
||||
{
|
||||
if (grantAccount != null)
|
||||
{
|
||||
SetRequestHeader(CosRequestHeaderKey.X_COS_GRANT_WRITE, grantAccount.GetGrantAccounts());
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 赋予被授权者所有的权限
|
||||
/// <see cref="Model.Tag.GrantAccount"/>
|
||||
/// </summary>
|
||||
/// <param name="grantAccount"></param>
|
||||
public void SetXCosReadWrite(GrantAccount grantAccount)
|
||||
{
|
||||
if (grantAccount != null)
|
||||
{
|
||||
SetRequestHeader(CosRequestHeaderKey.X_COS_GRANT_FULL_CONTROL, grantAccount.GetGrantAccounts());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
16
COSXML/Model/Object/PutObjectACLResult.cs
Normal file
16
COSXML/Model/Object/PutObjectACLResult.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using System.Text;
|
||||
|
||||
namespace COSXML.Model.Object
|
||||
{
|
||||
/// <summary>
|
||||
/// 设置 对象 的ACL返回的结果
|
||||
/// <see cref="https://cloud.tencent.com/document/product/436/7748"/>
|
||||
/// </summary>
|
||||
public sealed class PutObjectACLResult : CosResult
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
182
COSXML/Model/Object/PutObjectRequest.cs
Normal file
182
COSXML/Model/Object/PutObjectRequest.cs
Normal file
@@ -0,0 +1,182 @@
|
||||
using COSXML.Common;
|
||||
using System.IO;
|
||||
using COSXML.Model.Tag;
|
||||
using COSXML.Utils;
|
||||
using COSXML.CosException;
|
||||
using COSXML.Network;
|
||||
|
||||
namespace COSXML.Model.Object
|
||||
{
|
||||
/// <summary>
|
||||
/// 简单上传对象
|
||||
/// <see cref="https://cloud.tencent.com/document/product/436/7749"/>
|
||||
/// </summary>
|
||||
public sealed class PutObjectRequest : ObjectRequest
|
||||
{
|
||||
private static string TAG = typeof(PutObjectRequest).FullName;
|
||||
/// <summary>
|
||||
/// 本地文件路径
|
||||
/// </summary>
|
||||
private string srcPath;
|
||||
/// <summary>
|
||||
/// 上传文件指定起始位置
|
||||
/// </summary>
|
||||
private long fileOffset = 0L;
|
||||
/// <summary>
|
||||
/// 上传data数据
|
||||
/// </summary>
|
||||
private byte[] data;
|
||||
/// <summary>
|
||||
/// 上传指定内容的长度
|
||||
/// </summary>
|
||||
private long contentLength = -1L;
|
||||
/// <summary>
|
||||
/// 上传回调
|
||||
/// </summary>
|
||||
private COSXML.Callback.OnProgressCallback progressCallback;
|
||||
|
||||
/// <summary>
|
||||
/// 上传整个文件
|
||||
/// </summary>
|
||||
/// <param name="bucket"></param>
|
||||
/// <param name="key"></param>
|
||||
/// <param name="srcPath"></param>
|
||||
public PutObjectRequest(string bucket, string key, string srcPath)
|
||||
:this(bucket, key, srcPath, -1L, -1L)
|
||||
{
|
||||
|
||||
}
|
||||
/// <summary>
|
||||
/// 上传文件的指定内容
|
||||
/// </summary>
|
||||
/// <param name="bucket"></param>
|
||||
/// <param name="key"></param>
|
||||
/// <param name="srcPath"></param>
|
||||
/// <param name="fileOffset">文件指定起始位置</param>
|
||||
/// <param name="needSendLength">文件指定内容长度</param>
|
||||
public PutObjectRequest(string bucket, string key, string srcPath, long fileOffset, long needSendLength)
|
||||
:base(bucket, key)
|
||||
{
|
||||
this.method = CosRequestMethod.PUT;
|
||||
this.srcPath = srcPath;
|
||||
this.fileOffset = fileOffset < 0 ? 0 : fileOffset;
|
||||
this.contentLength = needSendLength < 0 ? -1L : needSendLength;
|
||||
}
|
||||
/// <summary>
|
||||
/// 上传data数据
|
||||
/// </summary>
|
||||
/// <param name="bucket"></param>
|
||||
/// <param name="key"></param>
|
||||
/// <param name="data"></param>
|
||||
public PutObjectRequest(string bucket, string key, byte[] data) : base(bucket, key)
|
||||
{
|
||||
this.method = CosRequestMethod.PUT;
|
||||
this.data = data;
|
||||
}
|
||||
/// <summary>
|
||||
/// 上传回调
|
||||
/// </summary>
|
||||
/// <param name="progressCallback"></param>
|
||||
public void SetCosProgressCallback(COSXML.Callback.OnProgressCallback progressCallback)
|
||||
{
|
||||
this.progressCallback = progressCallback;
|
||||
}
|
||||
|
||||
public override void CheckParameters()
|
||||
{
|
||||
if (srcPath == null && data == null) throw new CosClientException((int)(CosClientError.INVALID_ARGUMENT), "data source = null");
|
||||
if (srcPath != null)
|
||||
{
|
||||
if (!File.Exists(srcPath)) throw new CosClientException((int)(CosClientError.INVALID_ARGUMENT), "file not exist");
|
||||
}
|
||||
base.CheckParameters();
|
||||
}
|
||||
|
||||
public override Network.RequestBody GetRequestBody()
|
||||
{
|
||||
RequestBody body = null;
|
||||
if (srcPath != null)
|
||||
{
|
||||
FileInfo fileInfo = new FileInfo(srcPath);
|
||||
if (contentLength == -1 || contentLength + fileOffset > fileInfo.Length)
|
||||
{
|
||||
contentLength = fileInfo.Length - fileOffset;
|
||||
}
|
||||
body = new FileRequestBody(srcPath, fileOffset, contentLength);
|
||||
body.ProgressCallback = progressCallback;
|
||||
}
|
||||
else if (data != null)
|
||||
{
|
||||
body = new ByteRequestBody(data);
|
||||
body.ProgressCallback = progressCallback;
|
||||
}
|
||||
return body;
|
||||
}
|
||||
/// <summary>
|
||||
/// 定义 Object 的 acl 属性。有效值:private,public-read-write,public-read;默认值:private
|
||||
/// <see cref="Common.CosACL"/>
|
||||
/// </summary>
|
||||
/// <param name="cosACL"></param>
|
||||
public void SetCosACL(string cosACL)
|
||||
{
|
||||
if (cosACL != null)
|
||||
{
|
||||
SetRequestHeader(CosRequestHeaderKey.X_COS_ACL, cosACL);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 最大上传速度,单位是 bit/s
|
||||
/// </summary>
|
||||
/// <param name="start"></param>
|
||||
public void LimitTraffic(long rate) {
|
||||
SetRequestHeader(CosRequestHeaderKey.X_COS_TRAFFIC_LIMIT, rate.ToString());
|
||||
}
|
||||
/// <summary>
|
||||
/// 定义 Object 的 acl 属性。有效值:private,public-read-write,public-read;默认值:private
|
||||
/// <see cref="Common.CosACL"/>
|
||||
/// </summary>
|
||||
/// <param name="cosACL"></param>
|
||||
public void SetCosACL(CosACL cosACL)
|
||||
{
|
||||
SetRequestHeader(CosRequestHeaderKey.X_COS_ACL, EnumUtils.GetValue(cosACL));
|
||||
}
|
||||
/// <summary>
|
||||
/// 赋予被授权者读的权限
|
||||
/// <see cref="Model.Tag.GrantAccount"/>
|
||||
/// </summary>
|
||||
/// <param name="grantAccount"></param>
|
||||
public void SetXCosGrantRead(GrantAccount grantAccount)
|
||||
{
|
||||
if (grantAccount != null)
|
||||
{
|
||||
SetRequestHeader(CosRequestHeaderKey.X_COS_GRANT_READ, grantAccount.GetGrantAccounts());
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 赋予被授权者写的权限
|
||||
/// <see cref="Model.Tag.GrantAccount"/>
|
||||
/// </summary>
|
||||
/// <param name="grantAccount"></param>
|
||||
public void SetXCosGrantWrite(GrantAccount grantAccount)
|
||||
{
|
||||
if (grantAccount != null)
|
||||
{
|
||||
SetRequestHeader(CosRequestHeaderKey.X_COS_GRANT_WRITE, grantAccount.GetGrantAccounts());
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 赋予被授权者所有的权限
|
||||
/// <see cref="Model.Tag.GrantAccount"/>
|
||||
/// </summary>
|
||||
/// <param name="grantAccount"></param>
|
||||
public void SetXCosReadWrite(GrantAccount grantAccount)
|
||||
{
|
||||
if (grantAccount != null)
|
||||
{
|
||||
SetRequestHeader(CosRequestHeaderKey.X_COS_GRANT_FULL_CONTROL, grantAccount.GetGrantAccounts());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
29
COSXML/Model/Object/PutObjectResult.cs
Normal file
29
COSXML/Model/Object/PutObjectResult.cs
Normal file
@@ -0,0 +1,29 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using System.Text;
|
||||
|
||||
namespace COSXML.Model.Object
|
||||
{
|
||||
/// <summary>
|
||||
/// 简单上传对象返回的结果
|
||||
/// <see cref="https://cloud.tencent.com/document/product/436/7749"/>
|
||||
/// </summary>
|
||||
public sealed class PutObjectResult : CosResult
|
||||
{
|
||||
/// <summary>
|
||||
/// 对象的eTag
|
||||
/// </summary>
|
||||
public string eTag;
|
||||
|
||||
internal override void InternalParseResponseHeaders()
|
||||
{
|
||||
List<string> values;
|
||||
this.responseHeaders.TryGetValue("ETag", out values);
|
||||
if (values != null && values.Count > 0)
|
||||
{
|
||||
eTag = values[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
66
COSXML/Model/Object/RestoreObjectRequest.cs
Normal file
66
COSXML/Model/Object/RestoreObjectRequest.cs
Normal file
@@ -0,0 +1,66 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using System.Text;
|
||||
using COSXML.Model.Tag;
|
||||
using COSXML.Common;
|
||||
using COSXML.Network;
|
||||
|
||||
namespace COSXML.Model.Object
|
||||
{
|
||||
/// <summary>
|
||||
/// 对一个通过 COS 归档为 archive 类型的对象进行恢复
|
||||
/// <see cref="https://cloud.tencent.com/document/product/436/12633"/>
|
||||
/// </summary>
|
||||
public sealed class RestoreObjectRequest : ObjectRequest
|
||||
{
|
||||
/// <summary>
|
||||
/// 用于恢复数据的配置
|
||||
/// <see cref="Model.Tag.RestoreConfigure"/>
|
||||
/// </summary>
|
||||
private RestoreConfigure restoreConfigure;
|
||||
|
||||
public RestoreObjectRequest(string bucket, string key)
|
||||
: base(bucket, key)
|
||||
{
|
||||
this.method = CosRequestMethod.POST;
|
||||
this.needMD5 = true;
|
||||
this.queryParameters.Add("restore", null);
|
||||
restoreConfigure = new RestoreConfigure();
|
||||
restoreConfigure.casJobParameters = new RestoreConfigure.CASJobParameters();
|
||||
}
|
||||
/// <summary>
|
||||
/// 设置临时副本的过期时间
|
||||
/// </summary>
|
||||
/// <param name="days"></param>
|
||||
public void SetExpireDays(int days)
|
||||
{
|
||||
if (days < 0) days = 0;
|
||||
restoreConfigure.days = days;
|
||||
}
|
||||
/// <summary>
|
||||
/// 恢复数据时,Tier 可以指定为 CAS 支持的三种恢复类型,分别为 Expedited、Standard、Bulk
|
||||
/// <see cref="Model.Tag.RestoreConfigure.Tier"/>
|
||||
/// </summary>
|
||||
/// <param name="tier"></param>
|
||||
public void SetTier(RestoreConfigure.Tier tier)
|
||||
{
|
||||
restoreConfigure.casJobParameters.tier = tier;
|
||||
}
|
||||
public void SetVersionId(string versionId)
|
||||
{
|
||||
if (versionId != null)
|
||||
{
|
||||
SetQueryParameter(CosRequestHeaderKey.VERSION_ID, versionId);
|
||||
}
|
||||
}
|
||||
|
||||
public override Network.RequestBody GetRequestBody()
|
||||
{
|
||||
string content = Transfer.XmlBuilder.BuildRestoreConfigure(restoreConfigure);
|
||||
byte[] data = Encoding.UTF8.GetBytes(content);
|
||||
ByteRequestBody body = new ByteRequestBody(data);
|
||||
return body;
|
||||
}
|
||||
}
|
||||
}
|
||||
16
COSXML/Model/Object/RestoreObjectResult.cs
Normal file
16
COSXML/Model/Object/RestoreObjectResult.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using System.Text;
|
||||
|
||||
namespace COSXML.Model.Object
|
||||
{
|
||||
/// <summary>
|
||||
/// 对一个通过 COS 归档为 archive 类型的对象进行恢复返回的结果
|
||||
/// <see cref="https://cloud.tencent.com/document/product/436/12633"/>
|
||||
/// </summary>
|
||||
public sealed class RestoreObjectResult : CosResult
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
90
COSXML/Model/Object/SelectObjectRequest.cs
Normal file
90
COSXML/Model/Object/SelectObjectRequest.cs
Normal file
@@ -0,0 +1,90 @@
|
||||
using System.Text;
|
||||
using COSXML.Common;
|
||||
using COSXML.Network;
|
||||
using COSXML.Model.Tag;
|
||||
using COSXML.CosException;
|
||||
|
||||
namespace COSXML.Model.Object
|
||||
{
|
||||
public sealed class SelectObjectRequest : ObjectRequest
|
||||
{
|
||||
private string expression;
|
||||
|
||||
private string expressionType = "SQL";
|
||||
|
||||
private ObjectSelectionFormat inputFormat;
|
||||
|
||||
private ObjectSelectionFormat outputFormat;
|
||||
|
||||
internal COSXML.Callback.OnProgressCallback progressCallback;
|
||||
|
||||
internal string outputFilePath;
|
||||
|
||||
|
||||
public SelectObjectRequest(string bucket, string key)
|
||||
: base(bucket, key)
|
||||
{
|
||||
this.method = CosRequestMethod.POST;
|
||||
this.queryParameters.Add("select", null);
|
||||
this.queryParameters.Add("select-type", "2");
|
||||
}
|
||||
|
||||
public SelectObjectRequest outputToFile(string filePath) {
|
||||
outputFilePath = filePath;
|
||||
return this;
|
||||
}
|
||||
|
||||
public SelectObjectRequest setExpression(string expression) {
|
||||
this.expression = expression;
|
||||
return this;
|
||||
}
|
||||
|
||||
public SelectObjectRequest setExpressionType(string expressionType) {
|
||||
this.expressionType = expressionType;
|
||||
return this;
|
||||
}
|
||||
|
||||
public SelectObjectRequest setInputFormat(ObjectSelectionFormat inputFormat) {
|
||||
this.inputFormat = inputFormat;
|
||||
return this;
|
||||
}
|
||||
|
||||
public SelectObjectRequest setOutputFormat(ObjectSelectionFormat outputFormat) {
|
||||
this.outputFormat = outputFormat;
|
||||
return this;
|
||||
}
|
||||
|
||||
public SelectObjectRequest SetCosProgressCallback(COSXML.Callback.OnProgressCallback progressCallback)
|
||||
{
|
||||
this.progressCallback = progressCallback;
|
||||
return this;
|
||||
}
|
||||
|
||||
public override void CheckParameters()
|
||||
{
|
||||
base.CheckParameters();
|
||||
|
||||
if (expression == null) {
|
||||
throw new CosClientException((int)CosClientError.INVALID_ARGUMENT,
|
||||
"expression is null");
|
||||
}
|
||||
if (inputFormat == null) {
|
||||
throw new CosClientException((int)CosClientError.INVALID_ARGUMENT,
|
||||
"inputFormat is null");
|
||||
}
|
||||
if (outputFormat == null) {
|
||||
throw new CosClientException((int)CosClientError.INVALID_ARGUMENT,
|
||||
"outputFormat is null");
|
||||
}
|
||||
}
|
||||
|
||||
public override Network.RequestBody GetRequestBody()
|
||||
{
|
||||
string content = Transfer.XmlBuilder.BuildSelection(expression, expressionType, inputFormat,
|
||||
outputFormat, progressCallback != null);
|
||||
byte[] data = Encoding.UTF8.GetBytes(content);
|
||||
ByteRequestBody body = new ByteRequestBody(data);
|
||||
return body;
|
||||
}
|
||||
}
|
||||
}
|
||||
244
COSXML/Model/Object/SelectObjectResult.cs
Normal file
244
COSXML/Model/Object/SelectObjectResult.cs
Normal file
@@ -0,0 +1,244 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using System.Text;
|
||||
using System.IO;
|
||||
using COSXML.CosException;
|
||||
using COSXML.Common;
|
||||
using System.Xml;
|
||||
|
||||
namespace COSXML.Model.Object
|
||||
{
|
||||
public sealed class SelectObjectResult : CosResult
|
||||
{
|
||||
|
||||
public String searchContent;
|
||||
|
||||
public String outputFilePath;
|
||||
|
||||
public Stat stat;
|
||||
|
||||
private COSXML.Callback.OnProgressCallback progressCallback;
|
||||
|
||||
public sealed class Stat {
|
||||
public long BytesScanned;
|
||||
public long BytesProcessed;
|
||||
public long BytesReturned;
|
||||
|
||||
public override string ToString() {
|
||||
return string.Format("BytesScanned:{0}, BytesProcessed:{1}, BytesReturned:{2}",
|
||||
BytesScanned, BytesProcessed, BytesReturned);
|
||||
}
|
||||
}
|
||||
|
||||
internal override void ExternInfo(CosRequest cosRequest) {
|
||||
this.outputFilePath = ((SelectObjectRequest) cosRequest).outputFilePath;
|
||||
this.progressCallback = ((SelectObjectRequest) cosRequest).progressCallback;
|
||||
}
|
||||
|
||||
internal override void ParseResponseBody(System.IO.Stream inputStream,
|
||||
string contentType, long contentLength)
|
||||
{
|
||||
// Read One Message for each loop
|
||||
// readToString(inputStream);
|
||||
System.IO.Stream outputStream;
|
||||
if (outputFilePath != null) {
|
||||
outputStream = new System.IO.FileStream(outputFilePath, FileMode.Create);
|
||||
} else {
|
||||
outputStream = new MemoryStream();
|
||||
}
|
||||
|
||||
using (outputStream) {
|
||||
byte[] tempBuffer = new byte[4];
|
||||
|
||||
while(true) {
|
||||
tryRead(inputStream, tempBuffer, 0, 4);
|
||||
long messageEntireLength = bytes4ToInt(tempBuffer);
|
||||
|
||||
tryRead(inputStream, tempBuffer, 0, 4);
|
||||
long headerSectionLength = bytes4ToInt(tempBuffer);
|
||||
|
||||
tryRead(inputStream, tempBuffer, 0 ,4);
|
||||
long preludeCRC = bytes4ToInt(tempBuffer);
|
||||
|
||||
Dictionary<String, String> headers = new Dictionary<string, string>();
|
||||
|
||||
// read header
|
||||
long headerSectionRemainLength = headerSectionLength;
|
||||
while(headerSectionRemainLength > 0) {
|
||||
tryRead(inputStream, tempBuffer, 0, 1);
|
||||
int headerNameLength = bytes1ToInt(tempBuffer);
|
||||
|
||||
byte[] headerNameBuffer = new byte[headerNameLength];
|
||||
tryRead(inputStream, headerNameBuffer, 0, headerNameLength);
|
||||
String headerName = bytes2stringUTF8(headerNameBuffer);
|
||||
|
||||
// 7
|
||||
inputStream.ReadByte();
|
||||
|
||||
tryRead(inputStream, tempBuffer, 0, 2);
|
||||
int valueLength = bytes2ToInt(tempBuffer);
|
||||
|
||||
byte[] valueBuffer = new byte[valueLength];
|
||||
tryRead(inputStream, valueBuffer, 0, valueLength);
|
||||
String value = bytes2stringUTF8(valueBuffer);
|
||||
|
||||
if (headers.ContainsKey(headerName)) {
|
||||
headers.Remove(headerName);
|
||||
}
|
||||
headers.Add(headerName, value);
|
||||
|
||||
headerSectionRemainLength -= 1 + headerNameLength + 3 + valueLength;
|
||||
}
|
||||
|
||||
long payloadLength = messageEntireLength - headerSectionLength - 16;
|
||||
|
||||
string messageType;
|
||||
headers.TryGetValue(":message-type", out messageType);
|
||||
string eventType;
|
||||
headers.TryGetValue(":event-type", out eventType);
|
||||
Console.WriteLine("message = " + messageType + ", event = " + eventType);
|
||||
|
||||
bool isComplete = false;
|
||||
|
||||
if ("event".Equals(messageType)) {
|
||||
byte[] buffer;
|
||||
|
||||
switch (eventType)
|
||||
{
|
||||
case "Records":
|
||||
int totalRead = 0;
|
||||
buffer = new byte[1024];
|
||||
while(payloadLength > totalRead) {
|
||||
int readLength = (int) Math.Min(payloadLength - totalRead, 1024);
|
||||
int readBytes = tryRead(inputStream, buffer, 0, readLength);
|
||||
outputStream.Write(buffer, 0, readBytes);
|
||||
totalRead += readBytes;
|
||||
}
|
||||
break;
|
||||
|
||||
case "Progress":
|
||||
buffer = new byte[payloadLength];
|
||||
tryRead(inputStream, buffer, 0, (int) payloadLength);
|
||||
Stat stat = parseStatsBody(buffer);
|
||||
progressCallback(stat.BytesProcessed, stat.BytesScanned);
|
||||
break;
|
||||
|
||||
case "Cont":
|
||||
buffer = new byte[payloadLength];
|
||||
tryRead(inputStream, buffer, 0, (int) payloadLength);
|
||||
break;
|
||||
|
||||
case "Stats":
|
||||
buffer = new byte[payloadLength];
|
||||
tryRead(inputStream, buffer, 0, (int) payloadLength);
|
||||
this.stat = parseStatsBody(buffer);
|
||||
break;
|
||||
|
||||
case "End":
|
||||
default:
|
||||
isComplete = true;
|
||||
break;
|
||||
}
|
||||
} else if ("error".Equals(messageType)) {
|
||||
string errorCode = null;
|
||||
string errorMessage = null;
|
||||
headers.TryGetValue(":error-code", out errorCode);
|
||||
headers.TryGetValue(":error-message", out errorMessage);
|
||||
|
||||
throw new System.IO.IOException(string.Format(
|
||||
"search error happends with code :{0} and message: {1}",
|
||||
errorCode, errorMessage));
|
||||
}
|
||||
|
||||
if (isComplete) {
|
||||
if (outputFilePath == null) {
|
||||
outputStream.Position = 0;
|
||||
searchContent = readToString(outputStream);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
tryRead(inputStream, tempBuffer, 0 ,4);
|
||||
long messageCRC = bytes4ToInt(tempBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private int tryRead(System.IO.Stream inputStream, byte[] buffer, int offset, int count) {
|
||||
int read = 0;
|
||||
int maxRead = 10;
|
||||
int remainReadCount = count;
|
||||
|
||||
while (remainReadCount > 0 && maxRead-- > 0 & inputStream.CanRead) {
|
||||
read = inputStream.Read(buffer, count - remainReadCount, remainReadCount);
|
||||
remainReadCount -= read;
|
||||
}
|
||||
if (remainReadCount > 0) {
|
||||
throw new System.IO.IOException("input stream is end unexpectly !");
|
||||
}
|
||||
return count - remainReadCount;
|
||||
}
|
||||
|
||||
private Stat parseStatsBody(byte[] body) {
|
||||
XmlReader xmlReader = XmlReader.Create(new MemoryStream(body));
|
||||
Stat stat = new Stat();
|
||||
try {
|
||||
while (xmlReader.Read())
|
||||
{
|
||||
switch (xmlReader.NodeType)
|
||||
{
|
||||
case XmlNodeType.Element:
|
||||
if ("BytesScanned".Equals(xmlReader.Name, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
xmlReader.Read();
|
||||
stat.BytesScanned = Convert.ToInt64(xmlReader.Value);
|
||||
}
|
||||
else if ("BytesProcessed".Equals(xmlReader.Name, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
xmlReader.Read();
|
||||
stat.BytesProcessed = Convert.ToInt64(xmlReader.Value);
|
||||
}
|
||||
else if ("BytesReturned".Equals(xmlReader.Name, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
xmlReader.Read();
|
||||
stat.BytesReturned = Convert.ToInt64(xmlReader.Value);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
} catch (XmlException e) {
|
||||
Console.WriteLine(e.StackTrace);
|
||||
}
|
||||
return stat;
|
||||
}
|
||||
|
||||
private string readToString(System.IO.Stream inputStream) {
|
||||
string content = null;
|
||||
using (StreamReader reader = new StreamReader(inputStream))
|
||||
{
|
||||
content = reader.ReadToEnd();
|
||||
}
|
||||
return content;
|
||||
}
|
||||
|
||||
private string bytes2stringUTF8(byte[] data) {
|
||||
return System.Text.Encoding.UTF8.GetString(data);
|
||||
}
|
||||
|
||||
private int bytes2ToInt(byte[] data) {
|
||||
return ((data[0] & 0xFF) << 8) | (data[1] & 0xFF);
|
||||
}
|
||||
|
||||
private int bytes1ToInt(byte[] data) {
|
||||
return (data[0] & 0xFF);
|
||||
}
|
||||
|
||||
private long bytes4ToInt(byte[] data) {
|
||||
return ((data[0] & 0xFF) << 24) | ((data[1] & 0xFF) << 16)
|
||||
| ((data[2] & 0xFF) << 8) | (data[3] & 0xFF);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
160
COSXML/Model/Object/UploadPartCopyRequest.cs
Normal file
160
COSXML/Model/Object/UploadPartCopyRequest.cs
Normal file
@@ -0,0 +1,160 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using System.Text;
|
||||
using COSXML.Common;
|
||||
using COSXML.Model.Tag;
|
||||
using COSXML.CosException;
|
||||
|
||||
namespace COSXML.Model.Object
|
||||
{
|
||||
/// <summary>
|
||||
/// 分片复制
|
||||
/// <see cref="https://cloud.tencent.com/document/product/436/12633"/>
|
||||
/// </summary>
|
||||
public sealed class UploadPartCopyRequest : ObjectRequest
|
||||
{
|
||||
/// <summary>
|
||||
/// 拷贝的数据源
|
||||
/// <see cref="Model.Tag.CopySourceStruct"/>
|
||||
/// </summary>
|
||||
private CopySourceStruct copySourceStruct;
|
||||
/**Specified part number*/
|
||||
private int partNumber = -1;
|
||||
/**init upload generate' s uploadId by service*/
|
||||
private String uploadId = null;
|
||||
|
||||
public UploadPartCopyRequest(string bucket, string key, int partNumber, string uploadId)
|
||||
: base(bucket, key)
|
||||
{
|
||||
this.method = CosRequestMethod.PUT;
|
||||
this.partNumber = partNumber;
|
||||
this.uploadId = uploadId;
|
||||
}
|
||||
/// <summary>
|
||||
/// 设置拷贝数据源
|
||||
/// <see cref="Model.Tag.CopySourceStruct"/>
|
||||
/// </summary>
|
||||
/// <param name="copySource"></param>
|
||||
public void SetCopySource(CopySourceStruct copySource)
|
||||
{
|
||||
this.copySourceStruct = copySource;
|
||||
}
|
||||
/// <summary>
|
||||
/// 设置拷贝的分片范围
|
||||
/// </summary>
|
||||
/// <param name="start"></param>
|
||||
/// <param name="end"></param>
|
||||
public void SetCopyRange(long start, long end)
|
||||
{
|
||||
if (start >= 0 && end >= start)
|
||||
{
|
||||
string bytes = String.Format("bytes={0}-{1}", start, end);
|
||||
SetRequestHeader(CosRequestHeaderKey.X_COS_COPY_SOURCE_RANGE, bytes);
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 当 Object 在指定时间后被修改,则执行操作,否则返回 412。
|
||||
/// 可与 x-cos-copy-source-If-None-Match 一起使用,与其他条件联合使用返回冲突
|
||||
/// </summary>
|
||||
/// <param name="sourceIfModifiedSince"></param>
|
||||
public void SetCopyIfModifiedSince(string sourceIfModifiedSince)
|
||||
{
|
||||
if (sourceIfModifiedSince != null)
|
||||
{
|
||||
SetRequestHeader(CosRequestHeaderKey.X_COS_COPY_SOURCE_IF_MODIFIED_SINCE, sourceIfModifiedSince);
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 当 Object 在指定时间后未被修改,则执行操作,否则返回 412。
|
||||
/// 可与 x-cos-copy-source-If-Match 一起使用,与其他条件联合使用返回冲突。
|
||||
/// </summary>
|
||||
/// <param name="sourceIfUnmodifiedSince"></param>
|
||||
public void SetCopyIfUnmodifiedSince(string sourceIfUnmodifiedSince)
|
||||
{
|
||||
if (sourceIfUnmodifiedSince != null)
|
||||
{
|
||||
SetRequestHeader(CosRequestHeaderKey.X_COS_COPY_SOURCE_IF_UNMODIFIED_SINCE, sourceIfUnmodifiedSince);
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Object 的 Etag 和给定一致时,则执行操作,否则返回 412。
|
||||
/// 可与 x-cos-copy-source-If-Unmodified-Since 一起使用,与其他条件联合使用返回冲突。
|
||||
/// </summary>
|
||||
/// <param name="eTag"></param>
|
||||
public void SetCopyIfMatch(string eTag)
|
||||
{
|
||||
if (eTag != null)
|
||||
{
|
||||
SetRequestHeader(CosRequestHeaderKey.X_COS_COPY_SOURCE_IF_MATCH, eTag);
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 当 Object 的 Etag 和给定不一致时,则执行操作,否则返回 412。
|
||||
/// 可与 x-cos-copy-source-If-Modified-Since 一起使用,与其他条件联合使用返回冲突
|
||||
/// </summary>
|
||||
/// <param name="eTag"></param>
|
||||
public void SetCopyIfNoneMatch(string eTag)
|
||||
{
|
||||
if (eTag != null)
|
||||
{
|
||||
SetRequestHeader(CosRequestHeaderKey.X_COS_COPY_SOURCE_IF_NONE_MATCH, eTag);
|
||||
}
|
||||
}
|
||||
|
||||
public override void CheckParameters()
|
||||
{
|
||||
if (copySourceStruct == null)
|
||||
{
|
||||
throw new CosClientException((int)CosClientError.INVALID_ARGUMENT, "copy source = null");
|
||||
}
|
||||
else
|
||||
{
|
||||
copySourceStruct.CheckParameters();
|
||||
}
|
||||
if (requestUrlWithSign != null) return;
|
||||
base.CheckParameters();
|
||||
if (partNumber <= 0)
|
||||
{
|
||||
throw new CosClientException((int)CosClientError.INVALID_ARGUMENT, "partNumber < 1");
|
||||
}
|
||||
if (uploadId == null)
|
||||
{
|
||||
throw new CosClientException((int)CosClientError.INVALID_ARGUMENT, "uploadID = null");
|
||||
}
|
||||
}
|
||||
|
||||
protected override void InternalUpdateQueryParameters()
|
||||
{
|
||||
try
|
||||
{
|
||||
this.queryParameters.Add("partNumber", partNumber.ToString());
|
||||
}
|
||||
catch (ArgumentException)
|
||||
{
|
||||
this.queryParameters["partNumber"] = partNumber.ToString();
|
||||
}
|
||||
try
|
||||
{
|
||||
this.queryParameters.Add("uploadId", uploadId);
|
||||
}
|
||||
catch (ArgumentException)
|
||||
{
|
||||
this.queryParameters["uploadId"] = uploadId;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void InteranlUpdateHeaders()
|
||||
{
|
||||
try
|
||||
{
|
||||
this.headers.Add(CosRequestHeaderKey.X_COS_COPY_SOURCE, copySourceStruct.GetCopySouce());
|
||||
}
|
||||
catch (ArgumentException)
|
||||
{
|
||||
this.headers[CosRequestHeaderKey.X_COS_COPY_SOURCE] = copySourceStruct.GetCopySouce();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
33
COSXML/Model/Object/UploadPartCopyResult.cs
Normal file
33
COSXML/Model/Object/UploadPartCopyResult.cs
Normal file
@@ -0,0 +1,33 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using System.Text;
|
||||
using COSXML.Model.Tag;
|
||||
using COSXML.Transfer;
|
||||
|
||||
namespace COSXML.Model.Object
|
||||
{
|
||||
/// <summary>
|
||||
/// 分片复制返回的结果
|
||||
/// <see cref="https://cloud.tencent.com/document/product/436/12633"/>
|
||||
/// </summary>
|
||||
public sealed class UploadPartCopyResult : CosResult
|
||||
{
|
||||
/// <summary>
|
||||
/// 分片复制的结果信息
|
||||
/// <see cref="Model.Tag.CopyObject"/>
|
||||
/// </summary>
|
||||
public CopyObject copyObject;
|
||||
|
||||
internal override void ParseResponseBody(System.IO.Stream inputStream, string contentType, long contentLength)
|
||||
{
|
||||
copyObject = new CopyObject();
|
||||
XmlParse.ParseCopyObjectResult(inputStream, copyObject);
|
||||
}
|
||||
|
||||
public override string GetResultInfo()
|
||||
{
|
||||
return base.GetResultInfo() + (copyObject == null ? "" : "\n" + copyObject.GetInfo());
|
||||
}
|
||||
}
|
||||
}
|
||||
192
COSXML/Model/Object/UploadPartRequest.cs
Normal file
192
COSXML/Model/Object/UploadPartRequest.cs
Normal file
@@ -0,0 +1,192 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using System.Text;
|
||||
using COSXML.Common;
|
||||
using System.IO;
|
||||
using COSXML.Log;
|
||||
using COSXML.CosException;
|
||||
using COSXML.Network;
|
||||
|
||||
namespace COSXML.Model.Object
|
||||
{
|
||||
/// <summary>
|
||||
/// 分片上传
|
||||
/// <see cref="https://cloud.tencent.com/document/product/436/7750"/>
|
||||
/// </summary>
|
||||
public sealed class UploadPartRequest : ObjectRequest
|
||||
{
|
||||
private static string TAG = typeof(UploadPartRequest).FullName;
|
||||
/// <summary>
|
||||
/// 分片块编号
|
||||
/// </summary>
|
||||
private int partNumber;
|
||||
/// <summary>
|
||||
/// 分片上传的UploadId
|
||||
/// </summary>
|
||||
private string uploadId;
|
||||
/// <summary>
|
||||
/// 本地文件路径
|
||||
/// </summary>
|
||||
private string srcPath;
|
||||
/// <summary>
|
||||
/// 上传文件指定起始位置
|
||||
/// </summary>
|
||||
private long fileOffset = -1L;
|
||||
/// <summary>
|
||||
/// 上传指定内容的长度
|
||||
/// </summary>
|
||||
private long contentLength = -1L;
|
||||
/// <summary>
|
||||
/// 上传data数据
|
||||
/// </summary>
|
||||
private byte[] data;
|
||||
/// <summary>
|
||||
/// 上传回调
|
||||
/// </summary>
|
||||
private COSXML.Callback.OnProgressCallback progressCallback;
|
||||
|
||||
|
||||
private UploadPartRequest(string bucket, string key, int partNumber, string uploadId)
|
||||
: base(bucket, key)
|
||||
{
|
||||
this.method = CosRequestMethod.PUT;
|
||||
this.partNumber = partNumber;
|
||||
this.uploadId = uploadId;
|
||||
}
|
||||
/// <summary>
|
||||
/// 上传文件的指定内容
|
||||
/// </summary>
|
||||
/// <param name="bucket"></param>
|
||||
/// <param name="key"></param>
|
||||
/// <param name="partNumber"></param>
|
||||
/// <param name="uploadId"></param>
|
||||
/// <param name="srcPath"></param>
|
||||
/// <param name="fileOffset">文件指定起始位置</param>
|
||||
/// <param name="fileSendLength">文件指定内容长度</param>
|
||||
public UploadPartRequest(string bucket, string key, int partNumber, string uploadId, string srcPath, long fileOffset,
|
||||
long fileSendLength)
|
||||
: this(bucket, key, partNumber, uploadId)
|
||||
{
|
||||
this.srcPath = srcPath;
|
||||
this.fileOffset = fileOffset < 0 ? 0 : fileOffset;
|
||||
this.contentLength = fileSendLength < 0 ? -1L : fileSendLength;
|
||||
}
|
||||
/// <summary>
|
||||
/// 上传整个文件
|
||||
/// </summary>
|
||||
/// <param name="bucket"></param>
|
||||
/// <param name="key"></param>
|
||||
/// <param name="partNumber"></param>
|
||||
/// <param name="uploadId"></param>
|
||||
/// <param name="srcPath"></param>
|
||||
public UploadPartRequest(string bucket, string key, int partNumber, string uploadId, string srcPath)
|
||||
: this(bucket, key, partNumber, uploadId, srcPath, -1L, -1L)
|
||||
{ }
|
||||
/// <summary>
|
||||
/// 上传data数据
|
||||
/// </summary>
|
||||
/// <param name="bucket"></param>
|
||||
/// <param name="key"></param>
|
||||
/// <param name="partNumber"></param>
|
||||
/// <param name="uploadId"></param>
|
||||
/// <param name="data"></param>
|
||||
public UploadPartRequest(string bucket, string key, int partNumber, string uploadId, byte[] data)
|
||||
:this(bucket, key, partNumber, uploadId)
|
||||
{
|
||||
this.data = data;
|
||||
}
|
||||
/// <summary>
|
||||
/// 设置分片块编号
|
||||
/// </summary>
|
||||
/// <param name="partNumber"></param>
|
||||
public void SetPartNumber(int partNumber)
|
||||
{
|
||||
this.partNumber = partNumber;
|
||||
}
|
||||
/// <summary>
|
||||
/// 设置上传的UploadId
|
||||
/// </summary>
|
||||
/// <param name="uploadId"></param>
|
||||
public void SetUploadId(string uploadId)
|
||||
{
|
||||
this.uploadId = uploadId;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 最大上传速度,单位是 bit/s
|
||||
/// </summary>
|
||||
/// <param name="start"></param>
|
||||
public void LimitTraffic(long rate) {
|
||||
SetRequestHeader(CosRequestHeaderKey.X_COS_TRAFFIC_LIMIT, rate.ToString());
|
||||
}
|
||||
/// <summary>
|
||||
/// 设置回调
|
||||
/// </summary>
|
||||
/// <param name="progressCallback"></param>
|
||||
public void SetCosProgressCallback(COSXML.Callback.OnProgressCallback progressCallback)
|
||||
{
|
||||
this.progressCallback = progressCallback;
|
||||
}
|
||||
|
||||
public override void CheckParameters()
|
||||
{
|
||||
if (srcPath == null && data == null) throw new CosClientException((int)(CosClientError.INVALID_ARGUMENT), "data source = null");
|
||||
if (srcPath != null)
|
||||
{
|
||||
if (!File.Exists(srcPath)) throw new CosClientException((int)(CosClientError.INVALID_ARGUMENT), "file not exist");
|
||||
}
|
||||
if (requestUrlWithSign != null) return;
|
||||
base.CheckParameters();
|
||||
if (partNumber <= 0)
|
||||
{
|
||||
throw new CosClientException((int)CosClientError.INVALID_ARGUMENT, "partNumber < 1");
|
||||
}
|
||||
if (uploadId == null)
|
||||
{
|
||||
throw new CosClientException((int)CosClientError.INVALID_ARGUMENT, "uploadId = null");
|
||||
}
|
||||
}
|
||||
|
||||
protected override void InternalUpdateQueryParameters()
|
||||
{
|
||||
try
|
||||
{
|
||||
queryParameters.Add("uploadId", uploadId);
|
||||
}
|
||||
catch (ArgumentException)
|
||||
{
|
||||
queryParameters["uploadId"] = uploadId;
|
||||
}
|
||||
try
|
||||
{
|
||||
queryParameters.Add("partNumber", partNumber.ToString());
|
||||
}
|
||||
catch (ArgumentException)
|
||||
{
|
||||
queryParameters["partNumber"] = partNumber.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
public override Network.RequestBody GetRequestBody()
|
||||
{
|
||||
RequestBody body = null;
|
||||
if (srcPath != null)
|
||||
{
|
||||
FileInfo fileInfo = new FileInfo(srcPath);
|
||||
if (contentLength == -1 || contentLength + fileOffset > fileInfo.Length)
|
||||
{
|
||||
contentLength = fileInfo.Length - fileOffset;
|
||||
}
|
||||
body = new FileRequestBody(srcPath, fileOffset, contentLength);
|
||||
body.ProgressCallback = progressCallback;
|
||||
}
|
||||
else if (data != null)
|
||||
{
|
||||
body = new ByteRequestBody(data);
|
||||
body.ProgressCallback = progressCallback;
|
||||
}
|
||||
return body;
|
||||
}
|
||||
}
|
||||
}
|
||||
30
COSXML/Model/Object/UploadPartResult.cs
Normal file
30
COSXML/Model/Object/UploadPartResult.cs
Normal file
@@ -0,0 +1,30 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using System.Text;
|
||||
using System.IO;
|
||||
|
||||
namespace COSXML.Model.Object
|
||||
{
|
||||
/// <summary>
|
||||
/// 分片上传返回的结果
|
||||
/// <see cref="https://cloud.tencent.com/document/product/436/7750"/>
|
||||
/// </summary>
|
||||
public sealed class UploadPartResult : CosResult
|
||||
{
|
||||
/// <summary>
|
||||
/// 分片块的eTag
|
||||
/// </summary>
|
||||
public string eTag;
|
||||
|
||||
internal override void InternalParseResponseHeaders()
|
||||
{
|
||||
List<string> values;
|
||||
this.responseHeaders.TryGetValue("ETag", out values);
|
||||
if (values != null && values.Count > 0)
|
||||
{
|
||||
eTag = values[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user