Skip to content

Commit fcbced4

Browse files
authored
Merge branch 'master' into improve
2 parents 220f130 + fe8dec4 commit fcbced4

File tree

10 files changed

+244
-11
lines changed

10 files changed

+244
-11
lines changed

src/Api/Base/BaseOssCommand.cs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
using System;
2+
using System.IO;
23
using System.Net;
34
using System.Net.Http;
5+
using System.Text;
46
using System.Threading.Tasks;
57
using Cuiliang.AliyunOssSdk.Api.Common.Consts;
68
using Cuiliang.AliyunOssSdk.Entites;
@@ -67,8 +69,10 @@ public async Task<OssResult<TResult>> ExecuteAsync(HttpClient client)
6769
ServiceRequest request = BuildRequest();
6870

6971
//加入dateheader
72+
7073
request.Headers[HttpHeaders.Date] = DateUtils.FormatRfc822Date(DateTime.UtcNow);
7174

75+
7276
if (RequestContext.OssCredential.UseToken)
7377
{
7478
request.Headers[HttpHeaders.SecurityToken] = RequestContext.OssCredential.SecurityToken;
@@ -117,8 +121,15 @@ private async Task<OssResult<TResult>> ProcessResponseInternal(HttpResponseMessa
117121
//错误的http代码
118122
if (response.Content?.Headers.ContentLength > 0)
119123
{
124+
//var responseContent = await response.Content.ReadAsStreamAsync();
125+
//var errorResult =
126+
// SerializeHelper.Deserialize<ErrorResult>(responseContent);
127+
128+
var responseContent = await response.Content.ReadAsStringAsync();
120129
var errorResult =
121-
SerializeHelper.Deserialize<ErrorResult>(await response.Content.ReadAsStreamAsync());
130+
131+
SerializeHelper.Deserialize<ErrorResult>(responseContent);
132+
122133

123134
return new OssResult<TResult>()
124135
{

src/Api/Object/Get/GetObjectCommand.cs

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,14 @@
1-
using System.Net.Http;
1+
using System;
2+
using System.Diagnostics;
3+
using System.Globalization;
4+
using System.Linq;
5+
using System.Net.Http;
26
using System.Threading.Tasks;
37
using Cuiliang.AliyunOssSdk.Api.Base;
8+
using Cuiliang.AliyunOssSdk.Api.Common.Consts;
49
using Cuiliang.AliyunOssSdk.Entites;
510
using Cuiliang.AliyunOssSdk.Request;
11+
using Cuiliang.AliyunOssSdk.Utility;
612

713
namespace Cuiliang.AliyunOssSdk.Api.Object.Get
814
{
@@ -43,12 +49,47 @@ public override async Task<OssResult<GetObjectResult>> ParseResultAsync(HttpResp
4349
var result = new GetObjectResult();
4450
result.Headers = response.Headers;
4551
result.Content = response.Content;
52+
result.Metadata = Deserialize(response);
4653

4754
return new OssResult<GetObjectResult>()
4855
{
4956
IsSuccess = true,
5057
SuccessResult = result
5158
};
5259
}
60+
61+
private ObjectMetadata Deserialize(HttpResponseMessage response)
62+
{
63+
64+
var metadata = new ObjectMetadata();
65+
foreach (var header in response.Headers)
66+
{
67+
if (header.Key.StartsWith(OssHeaders.OssUserMetaPrefix, false, CultureInfo.InvariantCulture))
68+
{
69+
// The key of user in the metadata should not contain the prefix.
70+
metadata.UserMetadata.Add(header.Key.Substring(OssHeaders.OssUserMetaPrefix.Length),
71+
header.Value.FirstOrDefault());
72+
}
73+
else if (string.Equals(header.Key, HttpHeaders.ContentLength, StringComparison.InvariantCultureIgnoreCase))
74+
{
75+
// Content-Length. Parse should not fail.
76+
metadata.ContentLength = long.Parse(header.Value.FirstOrDefault(), CultureInfo.InvariantCulture);
77+
}
78+
else if (string.Equals(header.Key, HttpHeaders.ETag, StringComparison.InvariantCultureIgnoreCase))
79+
{
80+
metadata.ETag = OssUtils.TrimETag(header.Value.FirstOrDefault());
81+
}
82+
else if (string.Equals(header.Key, HttpHeaders.LastModified, StringComparison.InvariantCultureIgnoreCase))
83+
{
84+
metadata.LastModified = DateUtils.ParseRfc822Date(header.Value.FirstOrDefault());
85+
}
86+
else
87+
{
88+
// Treat the other headers just as strings.
89+
metadata.AddHeader(header.Key, header.Value);
90+
}
91+
}
92+
return metadata;
93+
}
5394
}
5495
}

src/Api/Object/Get/GetObjectResult.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using System.Net.Http;
22
using System.Net.Http.Headers;
3+
using Cuiliang.AliyunOssSdk.Entites;
34

45
namespace Cuiliang.AliyunOssSdk.Api.Object.Get
56
{
@@ -9,6 +10,6 @@ public class GetObjectResult
910

1011
public HttpContent Content { get; set; }
1112

12-
13+
public ObjectMetadata Metadata { get; set; }
1314
}
1415
}

src/Entites/OssRegions.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,14 @@ public class OssRegions
1717
// 华北 2
1818
public const string BeiJing = "oss-cn-beijing";
1919

20+
// 华北3 张家口
21+
public const string ZhangJiaKou = "oss-cn-zhangjiakou";
22+
23+
// 华北5 呼和浩特
24+
public const string HuHeHaoTe = "oss-cn-huhehaote";
25+
26+
27+
2028
// 华南 1
2129
public const string ShenZhen = "oss-cn-shenzhen";
2230

src/OssClient.cs

Lines changed: 74 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
using Cuiliang.AliyunOssSdk.Entites;
1818
using Cuiliang.AliyunOssSdk.Request;
1919
using Cuiliang.AliyunOssSdk.Utility;
20+
using Cuiliang.AliyunOssSdk.Utility.Authentication;
2021

2122
namespace Cuiliang.AliyunOssSdk
2223
{
@@ -51,9 +52,9 @@ public async Task<OssResult<ListBucketsResult>> ListBucketsAsync(string region)
5152
/// <param name="key"></param>
5253
/// <param name="file"></param>
5354
/// <returns></returns>
54-
public async Task<OssResult<PutObjectResult>> PutObjectAsync(BucketInfo bucket, string key, RequestContent file)
55+
public async Task<OssResult<PutObjectResult>> PutObjectAsync(BucketInfo bucket, string key, RequestContent file, IDictionary<string, string> extraHeaders = null)
5556
{
56-
var cmd = new PutObjectCommand(_requestContext, bucket, key, file, null);
57+
var cmd = new PutObjectCommand(_requestContext, bucket, key, file, extraHeaders);
5758

5859
return await cmd.ExecuteAsync(_client);
5960
}
@@ -66,16 +67,17 @@ public async Task<OssResult<PutObjectResult>> PutObjectAsync(BucketInfo bucket,
6667
/// <param name="content"></param>
6768
/// <param name="mimeType"></param>
6869
/// <returns></returns>
69-
public async Task<OssResult<PutObjectResult>> PutObjectAsync(BucketInfo bucket, string key, string content, string mimeType = "text/plain")
70+
public async Task<OssResult<PutObjectResult>> PutObjectAsync(BucketInfo bucket, string key, string content, string mimeType = "text/plain", ObjectMetadata meta = null, IDictionary<string, string> extraHeaders = null)
7071
{
7172
var file = new RequestContent()
7273
{
7374
ContentType = RequestContentType.String,
7475
StringContent = content,
75-
MimeType = mimeType
76+
MimeType = mimeType,
77+
Metadata = meta
7678
};
7779

78-
return await PutObjectAsync(bucket, key, file);
80+
return await PutObjectAsync(bucket, key, file, extraHeaders);
7981
}
8082

8183
/// <summary>
@@ -86,21 +88,45 @@ public async Task<OssResult<PutObjectResult>> PutObjectAsync(BucketInfo bucket,
8688
/// <param name="filePathName"></param>
8789
/// <returns></returns>
8890
public async Task<OssResult<PutObjectResult>> PutObjectByFileNameAsync(BucketInfo bucket, string key,
89-
string filePathName)
91+
string filePathName, ObjectMetadata meta = null, IDictionary<string, string> extraHeaders = null)
9092
{
9193
using (var stream = File.OpenRead(filePathName))
9294
{
9395
var file = new RequestContent()
9496
{
9597
ContentType = RequestContentType.Stream,
9698
StreamContent = stream,
97-
MimeType = MimeHelper.GetMime(filePathName)
99+
MimeType = MimeHelper.GetMime(filePathName),
100+
Metadata = meta
98101
};
99102

100-
return await PutObjectAsync(bucket, key, file);
103+
return await PutObjectAsync(bucket, key, file, extraHeaders);
101104
}
102105
}
103106

107+
/// <summary>
108+
/// 上传流
109+
/// </summary>
110+
/// <param name="bucket"></param>
111+
/// <param name="key"></param>
112+
/// <param name="content">内容流</param>
113+
/// <param name="mimeType"></param>
114+
/// <returns></returns>
115+
public async Task<OssResult<PutObjectResult>> PutObjectAsync(BucketInfo bucket, string key, Stream content,
116+
string mimeType = "application/octet-stream", ObjectMetadata meta = null, IDictionary<string, string> extraHeaders = null)
117+
{
118+
var file = new RequestContent()
119+
{
120+
ContentType = RequestContentType.Stream,
121+
StreamContent = content,
122+
MimeType = mimeType,
123+
Metadata = meta
124+
};
125+
126+
return await PutObjectAsync(bucket, key, file, extraHeaders);
127+
}
128+
129+
104130
/// <summary>
105131
/// 复制对象
106132
/// </summary>
@@ -202,5 +228,45 @@ public async Task<OssResult<GetObjectMetaResult>> GetObjectMetaAsync(BucketInfo
202228
var cmd = new GetObjectMetaCommand(_requestContext, bucket, key);
203229
return await cmd.ExecuteAsync(_client);
204230
}
231+
232+
/// <summary>
233+
/// 获取文件的下载链接
234+
/// </summary>
235+
/// <param name="bucket">bucket信息</param>
236+
/// <param name="storeKey">文件存储key</param>
237+
/// <param name="expireSeconds">签名超时时间秒数</param>
238+
/// <param name="imgStyle">阿里云图片处理样式</param>
239+
/// <returns></returns>
240+
public string GetFileDownloadLink(BucketInfo bucket, string storeKey, int expireSeconds, string imgStyle = null)
241+
{
242+
long seconds = (DateTime.UtcNow.AddSeconds(expireSeconds).Ticks - 621355968000000000) / 10000000;
243+
244+
string toSign = String.Format("GET\n\n\n{0}\n/{1}/{2}", seconds, bucket.BucketName, storeKey);
245+
if (!String.IsNullOrEmpty(imgStyle))
246+
{
247+
toSign += $"?x-oss-process=style/{imgStyle}";
248+
}
249+
250+
string sign = ServiceSignature.Create().ComputeSignature(
251+
_requestContext.OssCredential.AccessKeySecret, toSign);
252+
253+
string styleSegment = String.IsNullOrEmpty(imgStyle) ? String.Empty : $"x-oss-process=style/{imgStyle}&";
254+
string url = $"{bucket.BucketUri}{storeKey}?{styleSegment}OSSAccessKeyId={_requestContext.OssCredential.AccessKeyId}&Expires={seconds}&Signature={WebUtility.UrlEncode(sign)}";
255+
256+
return url;
257+
}
258+
259+
/// <summary>
260+
/// 生成直接post到oss的签名
261+
/// </summary>
262+
/// <param name="policy"></param>
263+
/// <returns></returns>
264+
public string ComputePostSignature(string policy)
265+
{
266+
string sign = ServiceSignature.Create().ComputeSignature(
267+
_requestContext.OssCredential.AccessKeySecret, policy);
268+
269+
return sign;
270+
}
205271
}
206272
}

src/Request/ServiceCaller.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ namespace Cuiliang.AliyunOssSdk.Request
1616
/// </summary>
1717
public class ServiceCaller
1818
{
19+
private readonly static HttpClient _client = new HttpClient();
1920
private RequestContext _requestContext;
2021
private readonly HttpClient _client;
2122

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Diagnostics;
4+
using System.Security.Cryptography;
5+
using System.Text;
6+
7+
namespace Cuiliang.AliyunOssSdk.Utility.Authentication
8+
{
9+
public class HmacSHA1Signature: ServiceSignature
10+
{
11+
private readonly Encoding _encoding = Encoding.UTF8;
12+
13+
public override string SignatureMethod
14+
{
15+
get { return "HmacSHA1"; }
16+
}
17+
18+
public override string SignatureVersion
19+
{
20+
get { return "1"; }
21+
}
22+
23+
protected override string ComputeSignatureCore(string key, string data)
24+
{
25+
Debug.Assert(!string.IsNullOrEmpty(data));
26+
27+
//using (var algorithm = KeyedHashAlgorithm.Create(
28+
// SignatureMethod.ToString().ToUpperInvariant()))
29+
//{
30+
// algorithm.Key = _encoding.GetBytes(key.ToCharArray());
31+
// return Convert.ToBase64String(
32+
// algorithm.ComputeHash(_encoding.GetBytes(data.ToCharArray())));
33+
//}
34+
35+
var bytes = _encoding.GetBytes(key);
36+
Trace.WriteLine("Key:" + key + " Data:" + data);
37+
Trace.WriteLine(bytes);
38+
39+
using (var algorithm = new HMACSHA1(_encoding.GetBytes(key)))
40+
{
41+
//algorithm.Key = _encoding.GetBytes(key.ToCharArray());
42+
var result = Convert.ToBase64String(
43+
algorithm.ComputeHash(_encoding.GetBytes(data.ToCharArray())));
44+
Trace.WriteLine("Result:" + result);
45+
return result;
46+
}
47+
}
48+
}
49+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
using System;
2+
3+
namespace Cuiliang.AliyunOssSdk.Utility.Authentication
4+
{
5+
public abstract class ServiceSignature
6+
{
7+
8+
public abstract string SignatureMethod { get; }
9+
10+
public abstract string SignatureVersion { get; }
11+
12+
public string ComputeSignature(String key, String data)
13+
{
14+
if (string.IsNullOrEmpty(key))
15+
throw new ArgumentException(
16+
"参数为空", "key");
17+
if (string.IsNullOrEmpty(data))
18+
throw new ArgumentException(
19+
"参数为空", "data");
20+
21+
22+
return ComputeSignatureCore(key, data);
23+
}
24+
25+
protected abstract string ComputeSignatureCore(string key, string data);
26+
27+
public static ServiceSignature Create()
28+
{
29+
return new HmacSHA1Signature();
30+
}
31+
32+
}
33+
}

src/Utility/OssUtils.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -354,5 +354,10 @@ internal static string JoinETag(IEnumerable<string> etags)
354354
// if (string.IsNullOrEmpty(accessKeySecret))
355355
// throw new ArgumentException(Resources.ExceptionIfArgumentStringIsNullOrEmpty, "accessKeySecret");
356356
//}
357+
358+
public static string TrimETag(string eTag)
359+
{
360+
return eTag != null ? eTag.Trim('\"') : null;
361+
}
357362
}
358363
}

src/Utility/SerializeHelper.cs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,24 @@ public static T Deserialize<T>(Stream xmlStream)
2828

2929
}
3030

31+
/// <summary>
32+
/// XML 文本 -》 对象
33+
/// </summary>
34+
/// <typeparam name="T"></typeparam>
35+
/// <param name="stringContent"></param>
36+
/// <returns></returns>
37+
public static T Deserialize<T>(string stringContent)
38+
{
39+
var serializer = new XmlSerializer(typeof(T));
40+
41+
using (TextReader reader = new StringReader(stringContent))
42+
{
43+
return (T)serializer.Deserialize(reader);
44+
}
45+
46+
47+
}
48+
3149
/// <summary>
3250
/// 将一个对象序列化为XML字符串
3351
/// </summary>

0 commit comments

Comments
 (0)