最近更新时间:2025-04-29 14:49:07
C# SDK基于KS3 API开发,支持.NET Framework 4.0及以上版本。使用该SDK开发网络应用,可轻松将数据安全存储至金山云对象存储。无论是独立网站,还是涵盖云端服务端与终端设备的应用架构,借助KS3存储及C# SDK,终端用户均可实现高速上传与下载,同时大幅减轻服务端负载,提升整体应用性能。
配置.net framework4.0
以上开发环境
由于在APP端明文存储AccessKey
、SecretKey
是极不安全的,因此推荐以下方式进行操作:
1. 开通KS3服务,注册账号。
2. 进入控制台,获取AccessKeyID 、AccessKeySecret。
代码示例如下所示:
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对应关系:点击查看。
术语名称 | 介绍 |
---|---|
Object(对象/文件) | 在KS3中,Object是用户操作的基本数据单元,单个Object大小介于0到48.8TB之间。每个Object由两部分构成:
|
Key(文件名) | Key作为Object的名称,采用UTF-8编码,长度不超过1024字符。其中可包含斜杠(/),在控制台中,带斜杠的Key会自动呈现目录层级结构,方便数据管理 。 |
其他术语请参考文档:概念与术语。
该操作表示列出当前用户的所有桶列表,可以查看每个桶的名称、创建时间以及所有者等信息。
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;
}
该操作表示删除桶。
private static bool deleteBucket()
{
// Delete Bucket
try
{
ks3Client.deleteBucket(bucketName);
}
catch(System.Exception e)
{
return false;
}
return true;
}
该操作表示列出某个桶下的所有的文件,单次列举返回文件数量上限为是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;
}
该操作表示获取某个桶的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;
}
该操作表示列出当前正在执行的分块上传任务。
private static ListMultipartUploadsResult listMultipartUploads(string bucket, string objKey, string uploadId) {
ListMultipartUploadsRequest request = new ListMultipartUploadsRequest(bucket, objKey, uploadId);
ListMultipartUploadsResult result = ks3Client.getListMultipartUploads(request);
return result;
}
该操作表示新建一个桶。
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桶名称要求全局唯一。
该操作表示设置某个桶的访问控制权限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;
}
该操作表示删除文件。
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;
}
该操作表示下载文件。
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;
}
该操作表示获取桶的访问控制权限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;
}
该操作表示上传文件。
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;
}
该操作表示修改文件的访问控制权限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;
}
该操作表示复制文件。
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;
}
该操作表示分块上传文件。
/**
* 初始化分块上传,服务端会返回一个全局唯一的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);
private static void getObjUrl() {
DateTime date = DateTime.Now;
date=date.AddMinutes(5);//指定签名有效期
String url = ks3Client.generatePresignedUrl("YourBucketName", "YourKey", date);
Console.WriteLine("url:"+url);
}
使用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;
}
}
}
纯净模式