阿里云的对象存储:https://www.aliyun.com/product/oss?spm=5176.8142029.388261.220.tpdG6e
Delphi版本:Embarcadero® Delphi 10.2 Version 25.0.26309.314
其开发文档中没有提供Delphi的SDK,参考javascript的SDK,大致修改后可以运作:
unit wxhAliYun_OSS;
interface
uses
REST.Client,system.JSON,system.SysUtils;
function invokeAliOSS(req:TRESTRequest;objName,method,body:string):string;
implementation
uses
REST.Types,DateUtils,EncdDecd,cHash,System.Classes;
function DateTimeToGMT(const ADate:TDateTime):string;
const
WEEK:array[1..7] of PChar = ('Sun','Mon','Tue','Wed','Thu','Fri','Sat');
MonthDig:array[1..12] of PChar =
('Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec');
var
wWeek,wYear,wMonth,wDay,wHour,wMin,wSec,wMilliSec:Word;
sWeek,sMonth:string;
begin
DecodeDateTime(ADate,wYear,wMonth,wDay,wHour,wMin,wSec,wMilliSec);
wWeek := DayOfWeek(ADate);
sWeek := WEEK[wWeek];
sMonth := MonthDig[wMonth];
Result := Format('%s, %.2d %s %d %.2d:%.2d:%.2d GMT',[sWeek,wDay,sMonth,wYear,wHour,wMin,wSec]);
end;
//加密算法来自http://fundementals.sourceforge.net
function signString(source, secret:AnsiString):string;
var d:T160BitDigest;
begin
d:=CalcHMAC_SHA1(secret,source);
Result:=EncodeBase64(@d.Bytes,length(d.Bytes));
end;
function composeStringToSign(method, contentMD5,contentType,date,signHeaders,resource:string):string;
begin
Result:= method+#10+contentMD5+#10+contentType+#10+date+#10+signHeaders+#10+resource;
end;
function invokeAliOSS(req:TRESTRequest;objName:string;method,body:string):string;
var
vItem:TRESTRequestParameter;
stringToSign,signature,sDate,resource,accessKeyId,accessKeySecret:string;
bucketID,path,host,sContentType,contentMD5:string;
contentType:TRESTContentType;
d:T128BitDigest;
begin
bucketID:='你的桶';
path:='/'+objName;
host:=bucketID+'.oss-cn-shanghai.aliyuncs.com';
contentType:=TRESTContentType.ctAPPLICATION_OCTET_STREAM;
sContentType:='application/octet-stream';//'application/json';
accessKeyId:='你的key';
accessKeySecret:='你的密钥';
//sDate:='Sat, 02 Sep 2017 03:08:12 GMT';
sDate:=DateTimeToGMT(TTimeZone.Local.ToUniversalTime(now()));
resource:='/'+bucketID+'/'+objName;
req.ClearBody();
req.Params.Clear();
//req.Client.BaseURL:='http://localhost:8080'+path;
req.Client.BaseURL:='http://'+host+path;
d:=CalcMD5(body);
contentMD5:=EncodeBase64(@d.Bytes,Length(d.Bytes));
stringToSign := composeStringToSign(
method,
contentMD5,
sContentType,
sDate,
'',
resource);
signature := signString(stringToSign,accessKeySecret);
vItem:=req.Params.AddItem;
vItem.Kind:=TRESTRequestParameterKind.pkHTTPHEADER;
vItem.ContentType:=contentType;
vItem.Options:=[TRESTRequestParameterOption.poDoNotEncode];
vItem.Name:='authorization';
vItem.Value:='OSS '+accessKeyId+':'+signature;
vItem:=req.Params.AddItem;
vItem.Kind:=TRESTRequestParameterKind.pkHTTPHEADER;
vItem.ContentType:=contentType;
vItem.Options:=[TRESTRequestParameterOption.poDoNotEncode];
vItem.Name:='host';
vItem.Value:=host;
vItem:=req.Params.AddItem;
vItem.Kind:=TRESTRequestParameterKind.pkHTTPHEADER;
vItem.ContentType:=contentType;
vItem.Options:=[TRESTRequestParameterOption.poDoNotEncode];
vItem.Name:='date';
vItem.Value:=sDate;
vItem:=req.Params.AddItem;
vItem.Kind:=TRESTRequestParameterKind.pkHTTPHEADER;
vItem.ContentType:=contentType;
vItem.Options:=[TRESTRequestParameterOption.poDoNotEncode];
vItem.Name:='content-md5';
vItem.Value:=contentMD5;
req.Accept:=sContentType;
req.Client.ContentType:=sContentType;
req.AddBody(body);
if (method='PUT') then
req.Method:=TRESTRequestMethod.rmPUT
else if (method='GET') then
req.Method:=TRESTRequestMethod.rmGET;
req.Execute();
Result:=req.Response.Content;
end;
end.
其中,注意:
- MD5和HMAC-SHA1的算法是来自http://fundementals.sourceforge.net,Delphi自带的IdHMACSHA1运行不起来。
- 其中的oss-cn-shanghai.aliyuncs.com,与你申请的OSS所在物理区域有关,需要根据实际情况调整。
客户端调用方法:
procedure TFormRanks.FormShow(Sender: TObject);
var
data:string;
i: Integer;
users:TJSONArray;
begin
//从阿里云的对象存储服务获取数据
data:=wxhAliYun_OSS.invokeAliOSS(RESTRequest1,'scores','GET','');
users:=TJSONArray(TJSONObject.ParseJSONValue(data));
//使用阿里云引擎,2016年时该服务关闭了。
{RESTClient1.BaseURL:='http://flowers2016.aliapp.com/getRanks';
RESTRequest1.Execute;
users:=TJSONArray(RESTResponse1.JSONValue);}
Grid1.RowCount:=users.Size;
for i := 0 to users.Size-1 do
begin
self.Grid1.Cells[0,i]:=InttoStr(i+1);
self.Grid1.Cells[1,i]:=users.Items[i].GetValue<string>('userID');
self.Grid1.Cells[2,i]:=users.Items[i].GetValue<string>('score');
self.Grid1.Cells[3,i]:=users.Items[i].GetValue<string>('score')+'/'+users.Items[i].GetValue<string>('cellCount');
end;
end;