全部文档
当前文档

暂无内容

如果没有找到您期望的内容,请尝试其他搜索词

文档中心

C#

最近更新时间:2025-04-29 14:49:07

目录


1. 概述

C# SDK基于KS3 API开发,支持.NET Framework 4.0及以上版本。使用该SDK开发网络应用,可轻松将数据安全存储至金山云对象存储。无论是独立网站,还是涵盖云端服务端与终端设备的应用架构,借助KS3存储及C# SDK,终端用户均可实现高速上传与下载,同时大幅减轻服务端负载,提升整体应用性能。

2. 环境准备

由于在APP端明文存储AccessKeySecretKey是极不安全的,因此推荐以下方式进行操作:

3. 初始化

3.1 获取密钥

1. 开通KS3服务,注册账号

2. 进入控制台,获取AccessKeyID 、AccessKeySecret。

3.2 初始化客户端

代码示例如下所示:

String accessKey = "YOUR ACCESS KEY";
String secretKey = "YOUR SECRET KEY";
String bucketName = "YOUR BUCKET NAME";
String endPoint = "ks3-cn-beijing.ksyuncs.com"; //此处以北京region为例
ks3Client = new KS3Client(accessKey, secretKey);
ks3Client.setEndpoint(endPoint);

Endpoint与Region对应关系:点击查看

3.3 常用术语介绍

术语名称

介绍

Object(对象/文件)

在KS3中,Object是用户操作的基本数据单元,单个Object大小介于0到48.8TB之间。每个Object由两部分构成:

  • Key:即Object的名称,采用 UTF-8 编码,编码后长度不超过 1024 字符。

  • Data:存储具体的数据内容。

Key(文件名)

Key作为Object的名称,采用UTF-8编码,长度不超过1024字符。其中可包含斜杠(/),在控制台中,带斜杠的Key会自动呈现目录层级结构,方便数据管理 。

其他术语请参考文档:概念与术语

4. 使用示例

4.1 List Buckets

该操作表示列出当前用户的所有桶列表,可以查看每个桶的名称、创建时间以及所有者等信息。

private static bool listBuckets()
{
    // List Buckets
    try
    {
        IList < Bucket > bucketsList = ks3Client.listBuckets();
        foreach(Bucket b in bucketsList)
        {
            Console.WriteLine(b.ToString());
        }
    }
    catch(System.Exception e)
    {
        return false;
    }
    return true;
}

4.2 DELETE Bucket

该操作表示删除桶。

private static bool deleteBucket()
{
    // Delete Bucket
    try
    {
        ks3Client.deleteBucket(bucketName);
    }
    catch(System.Exception e)
    {
        return false;
    }
    return true;
}

4.3 List Objects

该操作表示列出某个桶下的所有的文件,单次列举返回文件数量上限为是1000个。

private static bool listObjects()
{
    try
    {
        // List Objects
        Console.WriteLine("--- List Objects: ---");
        ObjectListing objects = ks3Client.listObjects(bucketName);
        Console.WriteLine(objects.ToString());
        Console.WriteLine("---------------------\n");

        // Get Object Metadata
        Console.WriteLine("--- Get Object Metadata ---");
        ObjectMetadata objMeta = ks3Client.getObjectMetadata(bucketName, objKeyName);
        Console.WriteLine(objMeta.ToString());
        Console.WriteLine("---------------------------\n");
    }
    catch(System.Exception e)
    {
        Console.WriteLine(e.ToString());
        return false;
    }
    return true;
}

4.4 GET Bucket acl

该操作表示获取某个桶的ACL访问控制权限。

private static bool getBucketACL()
{
    // 获取 Bucket ACL
    try
    {
        Console.WriteLine("--- Get Bucket ACL: ---");
        AccessControlList acl = ks3Client.getBucketAcl(bucketName);
        Console.WriteLine("Bucket Name: " + bucketName);
        Console.WriteLine(acl.ToString());
        Console.WriteLine("-----------------------\n");
    }
    catch(System.Exception e)
    {
        Console.WriteLine(e.ToString());
        return false;
    }
    return true;
}

4.5 List Multipart Uploads

该操作表示列出当前正在执行的分块上传任务。

private static ListMultipartUploadsResult listMultipartUploads(string bucket, string objKey, string uploadId) {
    ListMultipartUploadsRequest request = new ListMultipartUploadsRequest(bucket, objKey, uploadId);
    ListMultipartUploadsResult result = ks3Client.getListMultipartUploads(request);
    return result;
}

4.6 Create Bucket

该操作表示新建一个桶。

private static bool createBucket()
{
    // Create Bucket
    try
    {
        Console.WriteLine("--- Create Bucket: ---");
        Console.WriteLine("Bucket Name: " + bucketName);
        Bucket bucket = ks3Client.createBucket(bucketName);
        Console.WriteLine("Success.");
        Console.WriteLine("----------------------\n");
    }
    catch(System.Exception e)
    {
        Console.WriteLine("Create Bucket Fail! " + e.ToString());
        return false;
    }
    return true;
}

如果出现409 conflict错误,说明创建的桶名称有冲突,KS3桶名称要求全局唯一。

4.7 PUT Bucket ACL

该操作表示设置某个桶的访问控制权限ACL。

private static bool setBucketACL()
{
    // 为bucket设置公共读写权限
    try
    {
        Console.WriteLine("--- Set Bucket ACL: ---");
        CannedAccessControlList cannedAcl = new CannedAccessControlList(CannedAccessControlList.PUBLICK_READ_WRITE);
        ks3Client.setBucketAcl(bucketName, cannedAcl);
        Console.WriteLine("Bucket Name: " + bucketName);
        Console.WriteLine("Success, now the ACL is:\n" + ks3Client.getBucketAcl(bucketName));
        Console.WriteLine("-----------------------\n");
    }
    catch(System.Exception e)
    {
        Console.WriteLine(e.ToString());
        return false;
    }
    return true;
}

4.8 DELETE Object

该操作表示删除文件。

private static bool deleteObject()
{
    // Delete Object
    try
    {
        Console.WriteLine("--- Delete Object: ---");
        ks3Client.deleteObject(bucketName, objKeyName);
        Console.WriteLine("Delete Object completed.");
        Console.WriteLine("---------------------\n");
    }
    catch(Exception e)
    {
        Console.WriteLine(e.ToString());
        return false;
    }
    return true;
}

4.9 GET Object

该操作表示下载文件。

private static bool getObject() {
    try {
        // GET Object为用户提供了object的下载,用户可以通过控制Range实现分块多线程下载
        Console.WriteLine("--- Download and Store in Memory ---");
        GetObjectRequest getShortContent = new GetObjectRequest(bucketName, objKeyName);
        getShortContent.setRange(0, 24);
        KS3Object ks3Object = ks3Client.getObject(getShortContent);
        StreamReader sr = new StreamReader(ks3Object.getObjectContent());
        Console.WriteLine("Content:\n" + sr.ReadToEnd());
        sr.Close();
        ks3Object.getObjectContent().Close();
        Console.WriteLine("------------------------------------\n");
    } catch(System.Exception e) {
        Console.WriteLine(e.ToString());
        return false;
    }
    try {
        // 直接下载并存储成文件
        Console.WriteLine("--- Download a File ---");
        // I need to get the Content-Length to set the listener.
        ObjectMetadata objectMetadata = ks3Client.getObjectMetadata(bucketName, objKeyName);
        SampleListener downloadListener = new SampleListener(objectMetadata.getContentLength());
        GetObjectRequest getObjectRequest = new GetObjectRequest(bucketName, objKeyName, new FileInfo(outFilePath));
        getObjectRequest.setProgressListener(downloadListener);
        KS3Object obj = ks3Client.getObject(getObjectRequest);
        obj.getObjectContent().Close(); // The file was opened in [KS3ObjectResponseHandler], so I close it first.
        Console.WriteLine("Success. See the file downloaded at {0}", outFilePath);
        Console.WriteLine("-----------------------\n");
    } catch(System.Exception e) {
        Console.WriteLine(e.ToString());
        return false;
    }
    return true;
}

4.10 GET Object ACL

该操作表示获取桶的访问控制权限ACL。

private static bool getObjectACL()
{
    //获取 Object ACL
    try
    {
        Console.WriteLine("--- Get Object ACL: ---");
        AccessControlList acl = ks3Client.getObjectAcl(bucketName, objKeyName);
        Console.WriteLine("Object Key: " + objKeyName);
        Console.WriteLine(acl.ToString());
        Console.WriteLine("-----------------------\n");
    }
    catch(System.Exception e)
    {
        Console.WriteLine(e.ToString());
        return false;
    }
    return true;
}

4.11 PUT Object

该操作表示上传文件。

private static bool putObject()
{
    try
    {
        //Put Object(upload a short content)
        //以流方式上传文件到KS3,Content-Type 默认为 application/octet-stream
        Console.WriteLine("--- Upload a Short Content: ---");
        String sampleContent = "This is a sample content.(25 characters before, included the 4 spaces)";
        Stream stream = new MemoryStream(Encoding.UTF8.GetBytes(sampleContent));
        PutObjectResult shortContentResult = ks3Client.putObject(bucketName, objKeyName, stream, null);
        Console.WriteLine("Upload Completed. eTag=" + shortContentResult.getETag() + ", MD5=" + shortContentResult.getContentMD5());
        Console.WriteLine("-------------------------------\n");

        //Put Object(upload a file)
        //以文件方式上传到KS3时,Content-Type 会默认匹配上传文件的后缀名
        Console.WriteLine("--- Upload a File ---");
        FileInfo file = new FileInfo("E:\\tool\\eclipse.rar");
        PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, objKeyName, file);
        SampleListener sampleListener = new SampleListener(file.Length);
        putObjectRequest.setProgressListener(sampleListener);
        PutObjectResult putObjectResult = ks3Client.putObject(putObjectRequest);
        Console.WriteLine("Upload Completed. eTag=" + putObjectResult.getETag() + ", MD5=" + putObjectResult.getContentMD5());
        Console.WriteLine("---------------------\n");
    }
    catch(System.Exception e)
    {
        Console.WriteLine(e.ToString());
        return false;
    }
    return true;
}

4.12 PUT Object ACL

该操作表示修改文件的访问控制权限ACL。

private static bool setObjectACL()
{
    // 设置Object ACL为公共读写
    try
    {
        Console.WriteLine("--- Set Object ACL: ---");
        CannedAccessControlList cannedAcl = new CannedAccessControlList(CannedAccessControlList.PUBLICK_READ_WRITE);
        Console.WriteLine("Object Key: " + objKeyName);
        ks3Client.setObjectAcl(bucketName, objKeyName, cannedAcl);
        Console.WriteLine("Success, now the ACL is:\n" + ks3Client.getObjectAcl(bucketName, objKeyName));
        Console.WriteLine("-----------------------\n");
    }
    catch(System.Exception e)
    {
        Console.WriteLine(e.ToString());
        return false;
    }
    return true;
}

4.13 PUT Object Copy

该操作表示复制文件。

public static bool copyObject() {
    try
    {
        Console.WriteLine("--- copyObject: ---");
        CopyObjectRequest copyObjectRequest = new CopyObjectRequest();
        copyObjectRequest.SourceObject = objKeyNameFileData;
        copyObjectRequest.SourceBucket = bucketName;
        copyObjectRequest.DestinationBucket = "test2-zzy-jr";
        copyObjectRequest.DestinationObject = objKeyNameFileData;
        // CannedAccessControlList cannedAcl=new CannedAccessControlList(CannedAccessControlList.PUBLICK_READ_WRITE);
        // copyObjectRequest.CannedAcl = cannedAcl;
        // 指定目标Object的元信息
        // var metadata = new ObjectMetadata();
        // metadata.setHeader(Headers.METADATA_DIRECTIVE, "REPLACE");
        // metadata.setHeader(Headers.CONTENT_TYPE, "text/html");
        // copyObjectRequest.Metadata = metadata;

        CopyObjectResult result = ks3Client.copyObject(copyObjectRequest);
        Console.WriteLine("---------------------\n");
    }
    catch (System.Exception e)
    {
        Console.WriteLine(e.ToString());
        return false;
    }

    return true;
}

4.14 Multipart Upload

该操作表示分块上传文件。

/**
     * 初始化分块上传,服务端会返回一个全局唯一的uploadid
     * **/
    private static InitiateMultipartUploadResult multipartUp()
    {
        InitiateMultipartUploadResult re=ks3Client.initiateMultipartUpload(bucketName, objKeyName);
        Console.WriteLine(re.ToString());
        return re;
    }
    /**
     * 分块上传例子
     * **/
    private static bool uploadPart() {
        string path = @"you file path";//上传文件路径,例如E:\tool\aa.rar
        InitiateMultipartUploadResult result=multipartUp();
        FileInfo file = new FileInfo(path);
        int part = 5 * 1024 * 1024;
        long numBytesToRead = file.Length;
        int i = 0;
        XElement root = new XElement("CompleteMultipartUpload");//初始化一个xml,以备分块上传完成后调用complete方法提交本次上传的文件以通知服务端合并分块
        //开始读取文件
        using (FileStream fs = new FileStream(path, FileMode.Open))
        {
            while (numBytesToRead > 0)
            {
                UploadPartRequest request = new UploadPartRequest(
                        result.getBucket(), result.getKey(), result.getUploadId(),
                        i + 1);
                //每次读取5M文件内容,如果最后一次内容不及5M则按实际大小取值
                int count = Convert.ToInt32((i * part + part) > file.Length ? file.Length - i * part : part);
                byte[] data = new byte[count];
                int n = fs.Read(data, 0, count);
                request.setInputStream(new MemoryStream(data));
                ProgressListener sampleListener = new SampleListener(count);//实例一个更新进度的监听类,实际使用中可自己定义实现
                request.setProgressListener(sampleListener);
                PartETag tag = ks3Client.uploadPart(request);//上传本次分块内容
                Console.WriteLine(tag.ToString());
                if (n == 0)
                    break;
                numBytesToRead -= n;
               
                XElement partE = new XElement("Part");
                partE.Add(new XElement("PartNumber", i + 1));
                partE.Add(new XElement("ETag", tag.geteTag()));
                root.Add(partE);
                i++;
            }
        }
        //所有分块上传完成后发起complete request,通知服务端合并分块
        CompleteMultipartUploadRequest completeRequest = new CompleteMultipartUploadRequest(result.getBucket(), result.getKey(), result.getUploadId());
        completeRequest.setContent(new MemoryStream(System.Text.Encoding.Default.GetBytes(root.ToString())));
        CompleteMultipartUploadResult completeResult = ks3Client.completeMultipartUpload(completeRequest);
        return true;
    }

    /**
     * 放弃本次上传
     * **/
    private static bool AbortMultipartUpload(string bucket, string objKey, string uploadId)
    {
        AbortMultipartUploadRequest request = new AbortMultipartUploadRequest(bucket, objKey, uploadId);
        ks3Client.AbortMultipartUpload(request);
        return true;
    }
/**
    * 多线程分块上传例子开始
    * **/
    static List<ManualResetEvent> manualEvents = new List<ManualResetEvent>();
    static List<Param> paras = new List<Param>();

    private static bool uploadPartMultithread()
    {
        string path = inFilePath;//上传文件路径,例如E:\tool\aa.rar
        InitiateMultipartUploadResult result = multipartUp();
        FileInfo file = new FileInfo(path);
        int part = 5 * 1024 * 1024;
        long numBytesToRead = file.Length;
        int i = 0;
        XElement root = new XElement("CompleteMultipartUpload");//初始化一个xml,以备分块上传完成后调用complete方法提交本次上传的文件以通知服务端合并分块
        //开始读取文件
        using (FileStream fs = new FileStream(path, FileMode.Open))
        {
            while (numBytesToRead > 0)
            {
                UploadPartRequest request = new UploadPartRequest(
                        result.getBucket(), result.getKey(), result.getUploadId(),
                        i + 1);
                //每次读取5M文件内容,如果最后一次内容不及5M则按实际大小取值
                int count = Convert.ToInt32((i * part + part) > file.Length ? file.Length - i * part : part);
                byte[] data = new byte[count];
                int n = fs.Read(data, 0, count);
                request.setInputStream(new MemoryStream(data));

                ManualResetEvent mre = new ManualResetEvent(false);
                manualEvents.Add(mre);

                Param pra = new Param();
                pra.mrEvent = mre;
                pra.praNum = i + 1;
                pra.request = request;
                paras.Add(pra);

                ThreadPool.QueueUserWorkItem(new WaitCallback(uploadPartTask), pra);
                if (n == 0)
                    break;
                numBytesToRead -= n;
                i++;
            }
        }

        WaitHandle.WaitAll(manualEvents.ToArray());

        for (int j = 0; j < paras.Count; j++)
        {
            XElement partE = new XElement("Part");
            partE.Add(new XElement("PartNumber", paras[j].praNum));
            partE.Add(new XElement("ETag", paras[j].etag));
            Console.WriteLine("==" + paras[j].praNum + ", etag=" + paras[j].etag);
            root.Add(partE);
        }

        //所有分块上传完成后发起complete request,通知服务端合并分块
        CompleteMultipartUploadRequest completeRequest = new CompleteMultipartUploadRequest(result.getBucket(), result.getKey(), result.getUploadId());
        completeRequest.setContent(new MemoryStream(System.Text.Encoding.Default.GetBytes(root.ToString())));
        CompleteMultipartUploadResult completeResult = ks3Client.completeMultipartUpload(completeRequest);
        return true;
    }

    private static void uploadPartTask(Object obj) {
        Param pra = (Param)obj;
        UploadPartRequest request = pra.request;
        PartETag tag = ks3Client.uploadPart(request);//上传本次分块内容
        if (tag.geteTag() != null) {
            pra.etag = tag.geteTag();                
            pra.mrEvent.Set();
            Console.WriteLine(tag.ToString());
        }
    }

    public class Param
    {
        public ManualResetEvent mrEvent;
        public UploadPartRequest request;
        public int praNum;
        public string etag;
    }
    /**
    * 多线程分块上传例子结束
    * */

注:中途想停止分块上传的话请调用AbortMultipartUpload(bucketname, objectkey, uploadId);

4.15 生成带签名的URL

private static void getObjUrl() {
DateTime date = DateTime.Now;
date=date.AddMinutes(5);//指定签名有效期
String url = ks3Client.generatePresignedUrl("YourBucketName", "YourKey", date);
Console.WriteLine("url:"+url);
}

4.16 计算及使用签名

使用KS3时,所有发送的非匿名请求都需要携带签名,KS3服务器端收到消息后会进行身份验证,验证成功则接受并执行请求,否则将会返回403错误信息并丢弃此请求。以下内容主要介绍V2签名算法在C#语言中的实现方式。

计算签名

如下所示为实现GetSign()方法入参信息:

参数名称

描述

request

实现了KS3.Request<T>接口的类型。为了正确计算签名,需要将一些值提前封装进该参数,包括:HTTP请求方法、Content-Type头、Content-MD5头、前缀为x-kss-的头、子资源参数

bucketName

桶名

objKeyName

对象名

ak

AccessKeyID

sk

SecretAccessKey

GetSign()方法将返回签名字符串,如下所示为代码示例:

using KS3.Model;
using KS3;
using KS3.Auth;
using KS3.Http;
using System.Text.RegularExpressions;
using KS3.Internal;

namespace Demo
{
    class Demo
    {
        private static string GetSign<T>(Request<T> request, string bucketName, string objKeyName, string ak, string sk) where T : KS3Request
        {
            string bucketEncode = UrlEncoder.encode(bucketName != null ? bucketName : "", Constants.DEFAULT_ENCODING);
            string keyEncode = UrlEncoder.encode(objKeyName != null ? objKeyName : "", Constants.DEFAULT_ENCODING);
            string resourcePath = "/" + (bucketEncode != null ? bucketEncode + "/" : "") +
                                  (keyEncode != null ? keyEncode : "");
            resourcePath = FilterSpecial(resourcePath);
            string canonicalString = RestUtils.makeKS3CanonicalString(request.getHttpMethod().ToString(), resourcePath, request, null);
            string signature = SignerUtils.base64(SignerUtils.hmac_sha1(sk, canonicalString));
            return "KSS " + ak + ":" + signature;
        }
        
        private static string FilterSpecial(string path)
        {
            if (string.IsNullOrEmpty(path)) return path;
            path = path.Replace("%5C", "/").Replace("//", "/%2F").Replace("%28", "(").Replace("%29", ")");
            path = Regex.Replace(path, "%7E", "~", RegexOptions.IgnoreCase);
            return path;
        }
    }
}
使用签名

如下所示为使用GetSign方法计算签名的通用示例:

using KS3.Model;
using KS3;
using KS3.Auth;
using KS3.Http;
using System;
using System.IO;
using System.Security.Cryptography;
using System.Text.RegularExpressions;
using KS3.Internal;

namespace Demo
{
    class Demo
    {
        private const string AccessKey = "YourAccessKey";
        private const string SecretKey = "YourSecretKey";
        
        private static void CommonSignDemo()
        {
            string bucketName = "YourBucketName";
            string objKeyName = "YourKeyName";
            // 初始化特定操作的请求对象。如简单上传使用 PutObjectRequest ,下载使用 GetObjectRequest 等
            FileInfo file = new FileInfo("YourFilePath");
            PutObjectRequest originalRequest = new PutObjectRequest(bucketName, objKeyName, file);
            // 初始化 DefaultRequest 对象
            Request<PutObjectRequest> request = new DefaultRequest<PutObjectRequest>(originalRequest);
            /*
             * 在 DefaultRequest 类型的对象中设置参与签名计算的值:
             *   http请求方法、Content-Type头、Content-MD5头、前缀为x-kss-的头、子资源参数
             */
            request.setHttpMethod(HttpMethod.PUT);
            request.setHeader("Content-Type", Mimetypes.getMimetype(file));
            request.setHeader("Date", "Wed, 10 Apr 2024 09:26:45 GMT");

            using (FileStream fileStream = file.OpenRead())
            {
                MD5 md5 = MD5.Create();
                request.setHeader("Content-MD5", Convert.ToBase64String(md5.ComputeHash(fileStream)));
            }

            request.setHeader("x-kss-xxx", "xxx");
            // 填写相关请求参数
            request.setParameter("xxx", null);
            request.setParameter("xxx", "xxx");
            // 计算签名并设置到请求对象的header中
            string sign = GetSign(request, bucketName, objKeyName, AccessKey, SecretKey);
            request.setHeader("Authorization", sign);

            Console.WriteLine(request.getHeaders()["Authorization"]);
        }
    }
}

具体用例如下所示:

using KS3.Model;
using KS3;
using KS3.Auth;
using KS3.Http;
using System;
using System.IO;
using System.Globalization;
using System.Net;
using System.Security.Cryptography;
using System.Text.RegularExpressions;
using KS3.Internal;

namespace Demo
{
    class Demo
    {
        private const string AccessKey = "YourAccessKey";
        private const string SecretKey = "YourSecretKey";
        private const string Endpoint = "ks3-cn-beijing.ksyuncs.com";

        static void Main(string[] args)
        {
            string bucketName = "YourBucketName";
            string objKeyName = "YourKeyName";
            // 列举桶
            ListBuckets();
            // 列举对象
            ListObjects(bucketName);
            // 获取对象acl
            GetObjectAcl(bucketName, objKeyName);
            // 删除对象
            DeleteObject(bucketName, objKeyName);
            // 上传对象
            PutObject(bucketName, objKeyName, "YourFilePath");
        }

        private static void ListBuckets()
        {
            ListBucketsRequest originalRequest = new ListBucketsRequest();
            Request<ListBucketsRequest> request = new DefaultRequest<ListBucketsRequest>(originalRequest);
            request.setHttpMethod(HttpMethod.GET);
            request.setHeader("Content-Type", Mimetypes.DEFAULT_MIMETYPE);
            request.setHeader("Date",
                DateTime.UtcNow.ToString("ddd, dd MMM yyyy HH':'mm':'ss 'GMT'",
                    CultureInfo.CreateSpecificCulture("en-US")));

            string sign = GetSign(request, null, null, AccessKey, SecretKey);
            request.setHeader("Authorization", sign);

            ClientConfiguration configuration = new ClientConfiguration();
            // configuration.setProtocol(Protocol.HTTPS);

            HttpWebRequest httpRequest = CreateHttpRequest(request, configuration, null, null);

            HttpWebResponse httpResponse = (HttpWebResponse)httpRequest.GetResponse();
            Console.WriteLine(httpResponse.StatusCode.ToString());
            Console.WriteLine(httpResponse.ToString());
        }

        private static void ListObjects(string bucketName)
        {
            ListObjectsRequest originalRequest = new ListObjectsRequest();
            originalRequest.setBucketName(bucketName);
            Request<ListObjectsRequest> request = new DefaultRequest<ListObjectsRequest>(originalRequest);
            request.setHttpMethod(HttpMethod.GET);
            request.setHeader("Content-Type", Mimetypes.DEFAULT_MIMETYPE);
            request.setHeader("Date",
                DateTime.UtcNow.ToString("ddd, dd MMM yyyy HH':'mm':'ss 'GMT'",
                    CultureInfo.CreateSpecificCulture("en-US")));
            request.setParameter("prefix", "p1");
            request.setParameter("marker", "p1a.txt");
            request.setParameter("delimiter", "/");
            request.setParameter("max-keys", "10");

            string sign = GetSign(request, bucketName, null, AccessKey, SecretKey);
            request.setHeader("Authorization", sign);

            ClientConfiguration configuration = new ClientConfiguration();
            // configuration.setProtocol(Protocol.HTTPS);

            HttpWebRequest httpRequest = CreateHttpRequest(request, configuration, bucketName, null);

            HttpWebResponse httpResponse = (HttpWebResponse)httpRequest.GetResponse();
            Console.WriteLine(httpResponse.StatusCode.ToString());
            Console.WriteLine(httpResponse.ToString());
        }

        private static void GetObjectAcl(string bucketName, string objKeyName)
        {
            GetObjectAclRequest originalRequest = new GetObjectAclRequest(bucketName, objKeyName);
            Request<GetObjectAclRequest> request = new DefaultRequest<GetObjectAclRequest>(originalRequest);
            request.setHttpMethod(HttpMethod.GET);
            request.setHeader("Content-Type", Mimetypes.DEFAULT_MIMETYPE);
            request.setHeader("Date",
                DateTime.UtcNow.ToString("ddd, dd MMM yyyy HH':'mm':'ss 'GMT'",
                    CultureInfo.CreateSpecificCulture("en-US")));
            request.setParameter("acl", null);

            string sign = GetSign(request, bucketName, objKeyName, AccessKey, SecretKey);
            request.setHeader("Authorization", sign);

            ClientConfiguration configuration = new ClientConfiguration();
            // configuration.setProtocol(Protocol.HTTPS);

            HttpWebRequest httpRequest = CreateHttpRequest(request, configuration, bucketName, objKeyName);

            HttpWebResponse httpResponse = (HttpWebResponse)httpRequest.GetResponse();
            Console.WriteLine(httpResponse.StatusCode.ToString());
            Console.WriteLine(httpResponse.ToString());
        }

        private static void DeleteObject(string bucketName, string objKeyName)
        {
            DeleteObjectRequest originalRequest = new DeleteObjectRequest(bucketName, objKeyName);
            Request<DeleteObjectRequest> request = new DefaultRequest<DeleteObjectRequest>(originalRequest);
            request.setHttpMethod(HttpMethod.DELETE);
            request.setHeader("Content-Type", Mimetypes.DEFAULT_MIMETYPE);
            request.setHeader("Date",
                DateTime.UtcNow.ToString("ddd, dd MMM yyyy HH':'mm':'ss 'GMT'",
                    CultureInfo.CreateSpecificCulture("en-US")));

            string sign = GetSign(request, bucketName, objKeyName, AccessKey, SecretKey);
            request.setHeader("Authorization", sign);

            ClientConfiguration configuration = new ClientConfiguration();
            // configuration.setProtocol(Protocol.HTTPS);

            HttpWebRequest httpRequest = CreateHttpRequest(request, configuration, bucketName, objKeyName);

            HttpWebResponse httpResponse = (HttpWebResponse)httpRequest.GetResponse();
            Console.WriteLine(httpResponse.StatusCode.ToString());
            Console.WriteLine(httpResponse.ToString());
        }

        private static void PutObject(string bucketName, string objKeyName, string filePath)
        {
            FileInfo file = new FileInfo(filePath);
            PutObjectRequest originalRequest = new PutObjectRequest(bucketName, objKeyName, file);
            Request<PutObjectRequest> request = new DefaultRequest<PutObjectRequest>(originalRequest);
            // 设置计算签名需要用到的参数
            request.setHttpMethod(HttpMethod.PUT);
            request.setHeader("Content-Type", Mimetypes.getMimetype(file));
            request.setHeader("Date",
                DateTime.UtcNow.ToString("ddd, dd MMM yyyy HH':'mm':'ss 'GMT'",
                    CultureInfo.CreateSpecificCulture("en-US")));
            request.setHeader("x-kss-storage-class", "STANDARD");
            using (FileStream fileStream = file.OpenRead())
            {
                MD5 md5 = MD5.Create();
                request.setHeader("Content-MD5", Convert.ToBase64String(md5.ComputeHash(fileStream)));
            }

            // 计算并设置签名头
            string sign = GetSign(request, bucketName, objKeyName, AccessKey, SecretKey);
            request.setHeader("Authorization", sign);

            // 设置上传文件所需参数
            request.setHeader("Content-Length", file.Length.ToString());
            request.setContent(file.OpenRead());

            ClientConfiguration configuration = new ClientConfiguration();
            // configuration.setProtocol(Protocol.HTTPS);

            HttpWebRequest httpRequest = CreateHttpRequest(request, configuration, bucketName, objKeyName);
            HttpWebResponse httpResponse = (HttpWebResponse)httpRequest.GetResponse();

            Console.WriteLine(httpResponse.StatusCode.ToString());
        }

        /**
         * 用来构建http请求对象
         */
        private static HttpWebRequest CreateHttpRequest<T>(Request<T> request, ClientConfiguration clientConfiguration,
            string bucketName, string objKeyName) where T : KS3Request
        {
            Uri uri = new Uri(clientConfiguration.getProtocol() + "://" + Endpoint);
            var newUriBuilder = new UriBuilder(Endpoint);
            if (bucketName != null)
            {
                newUriBuilder.Host = bucketName + '.' + uri.Host;
                uri = newUriBuilder.Uri;
            }

            request.setEndpoint(uri);
            string keyEncode = UrlEncoder.encode(objKeyName != null ? objKeyName : "", Constants.DEFAULT_ENCODING);
            string resourcePath = "/" + (keyEncode != null ? keyEncode : "");
            resourcePath = FilterSpecial(resourcePath);
            request.setResourcePath(resourcePath);

            return HttpRequestFactory.createHttpRequest(request, clientConfiguration);
        }
        
        private static string GetSign<T>(Request<T> request, string bucketName, string objKeyName, string ak, string sk)
            where T : KS3Request
        {
            string bucketEncode = UrlEncoder.encode(bucketName != null ? bucketName : "", Constants.DEFAULT_ENCODING);
            string keyEncode = UrlEncoder.encode(objKeyName != null ? objKeyName : "", Constants.DEFAULT_ENCODING);
            string resourcePath = "/" + (bucketEncode != null ? bucketEncode + "/" : "") +
                                  (keyEncode != null ? keyEncode : "");
            resourcePath = FilterSpecial(resourcePath);
            string canonicalString =
                RestUtils.makeKS3CanonicalString(request.getHttpMethod().ToString(), resourcePath, request, null);
            string signature = SignerUtils.base64(SignerUtils.hmac_sha1(sk, canonicalString));
            return "KSS " + ak + ":" + signature;
        }

        private static string FilterSpecial(string path)
        {
            if (string.IsNullOrEmpty(path)) return path;
            path = path.Replace("%5C", "/").Replace("//", "/%2F").Replace("%28", "(").Replace("%29", ")");
            path = Regex.Replace(path, "%7E", "~", RegexOptions.IgnoreCase);
            return path;
        }
    }
}

文档导读
纯净模式常规模式

纯净模式

点击可全屏预览文档内容
文档反馈