delphi Restful:客戶端實現的四種方式
摘要:轉載自https://blog.csdn.net/pulledup/article/details/104132753
一、NetHTTP技術體系: TNetHTTPClient; TNetHTTPRequest
二、REST技術體系:
TRESTClient; TRESTRequest; TRESTResponse; TRESTResponseDataSetAdapter
三、Indy技術體系:IdHTTP + IdSSLOpenSSL
四、瀏覽器客戶端技術體系:JavaScript+jQuery(Mobile)+Http DOM+Ajax
一、NetHTTP技術體系:
System.Net.HttpClient; System.Net.URLClient; System.Net.FileClient;
System.Net.Mime; System.Net.Socket; System.Net.HttpClientComponent;
非常強大!
優勢:
DX原生的:僅取決於操作系統,操作系統升級后,部署及其代碼不會受到任何影響;不受組件的版本影響;可方便地Rest
既能很好的支持TSession會話方式的基本鑒權,又能很好的支持AccessToken訪問令牌方式或代碼方式的高級鑒權,有專門的非可視化鑒權類(TCertificateList = class(TList<TCertificate>);)支持,需要自己寫代碼去實現
異常處理:強大、方便。
屬系統運行時刻庫
C:\Program Files (x86)\Embarcadero\Studio\20.0\source\rtl\net
對應的原生組件:
NetHTTPClient1: TNetHTTPClient;
NetHTTPRequest1: TNetHTTPRequest;
既可直接使用組件
NetHTTPClient1: TNetHTTPClient; NetHTTPRequest1: TNetHTTPRequest;
也可以不使用組件,而動態產生
官方案例1:同步多線程文件分段下載:
D:\開發測試\Samples\Object Pascal\RTL\HttpDownload\HttpDownloadDemo.dproj
C:\Users\Public\Documents\Embarcadero\Studio\20.0\Samples\Object Pascal\RTL\HttpDownload
官方案例2:異步單線程文件下載:
D:\開發測試\Samples\Object Pascal\RTL\HttpAsyncDownload\HttpAsyncDownloadDemo.dproj
C:\Users\Public\Documents\Embarcadero\Studio\20.0\Samples\Object Pascal\RTL\HttpAsyncDownload
第三方案例3:HTTPClient的Rest方法獲取Json數據&並行庫未來&異步任務
D:\開發測試\Samples\其它\myTestCode\DelphiCookbookThirdEdition\Chapter05\CODE\RECIPE07\
var
MainForm: TMainForm;
implementation
uses
System.Net.HTTPClient, System.JSON
, AsyncTask
, Converters
;
{$R *.dfm}
const
ACCESS_KEY = '58297a8c75e21d218b1da2c610b6f62c';
//:Token鑒權思路:初次給常數,下載令牌文件,再次登錄驗證令牌辦法的合法性
procedure TMainForm.FormCreate(Sender: TObject);
var ListPair:TStringList; ListObject:TStringList;
LStrRespContent:string;
//:以上我加的
//泛型異步任務:Rest調用數據、UI加載結果處理異常:FormCreate事前獲取幣種,保存到TStringList中:
begin
Async.Run<TStringList>(
function: TStringList //:異步任務:匿名線程執行函數:
var
LHTTP: THTTPClient;
LResp: IHTTPResponse;
LJObj: TJSONObject;
LJRates: TJSONObject;
I: Integer;
begin
LHTTP := THTTPClient.Create;
//:步驟1:THTTPClient實例化
try
LResp := LHTTP.Get(
'http://data.fixer.io/api/latest' //:baseURL:TURI的baseURL部分:包括Scheme(協議https://等)+Path(路徑)+Port(端口)等
+'?' //:FQuery:TURI查詢指令部分
+'access_key='+ACCESS_KEY //:TURIParameters:TURI參數部分(TNameValuePair名稱=數值的對,參數間用’&’分割)
//:在本例:access_key該參數相當於Token鑒權方式
);
//:步驟2:THTTPClient獲取URL的默認頭定義的響應接口IHTTPResponse
LStrRespContent:=LResp.ContentAsString(TEncoding.UTF8);
//:步驟3:響應接口IHTTPResponse以UTF8編碼獲取響應結果的內容字符串
LStrRespContent:=TConverters.JsonReformat(LStrRespContent,true);
//:步驟4:格式化獲取到的響應結果的內容字符串為縮進的JSon格式化的字符串
//:(便於閱讀和調試)
LJObj := TJSONObject.ParseJSONValue (LStrRespContent) as TJSONObject;
//:步驟5:解析:獲取到的響應結果的JSon格式化的字符串:為JSON對象:
try
LJRates := LJObj.GetValue<TJSONObject>('rates');
ListPair := TStringList.Create;
ListObject:=TStringList.Create;
//:我加的
Result := TStringList.Create;
for I := 0 to LJRates.Count - 1 do
begin
//ListPair.Add( LJRates.Pairs[I].JsonString.Value +' : '
//+ LJRates.Pairs[I].JsonValue.ToString );
ListObject.Add( LJRates.Pairs[I].JsonString.Value +'='
+ LJRates.Pairs[I].JsonValue.ToString );
ListPair.AddPair(LJRates.Pairs[I].JsonString.Value,
LJRates.Pairs[I].JsonValue.ToString,
ListObject );
//:我加的
Result.Add(LJRates.Pairs[I].JsonString.Value);
end;
Result.Sort;//:成功回調值TStringList索引排序
finally
LJObj.Free;
end;
finally
LHTTP.Free;
//:步驟7:釋放THTTPClient實例
end;
end,
procedure(const Strings: TStringList)
begin //:異步任務:主線程加載數據:
//:步驟6:UI加載解析后的數據:
Memo3.Clear;
Memo3.Lines.BeginUpdate;
Memo3.Lines.Add(LStrRespContent);
//:加載經過格式化的響應內容字符串
//:HTTP客戶端Rest請求的JSon對象值(各幣種對歐元)
Memo3.Lines.EndUpdate;
cbSymbol.Items.Assign(Strings);//:下拉框賦值
Memo1.Lines.Clear; Memo1.Lines.BeginUpdate;
//Memo1.Lines.Add( (ListPair.Objects[0] as TStrings).Text );
Memo1.Lines.Add( ListPair.Text );
//Memo1.Lines.Add( ListObject.Text );
Memo1.Lines.EndUpdate;
//:加載各幣種對歐元的實時匯率:
Memo2.Lines.Clear; Memo2.Lines.BeginUpdate;
Memo2.Lines.Add( LStrRespContent ); Memo2.Lines.EndUpdate;
//:我加的
end,
procedure(const ExceptParallel:Exception)
begin //:異步任務:異常處理:
if ExceptParallel.Message.Trim<>'' then
begin
ShowMessage('請求出錯了');
end;
end
);
end;
二、REST技術體系:
REST.Client; REST.Response.Adapter; REST.HttpClient; REST.Types;
REST.Json, REST.Json.Interceptors; REST.BindSource; REST.Utils;
REST.Authenticator.Basic; REST.Authenticator.OAuth;
TRESTClient的底層是THTTPClient: 繼承關系如下-> TRESTHTTP -> REST.Client-> THTTPClient.Create-> THTTPClient -> System.Net.HttpClient
DX原生的:僅取決於操作系統,操作系統升級后,部署及其代碼不會受到任何影響;不受組件的版本影響;可方便地Rest
//:這一組Rest客戶端組件只對返回Json數據有效,對流和Xml均無效:
強大,好用,簡單!
優勢:
1、REST.Json, REST.Json.Interceptors :體系中這套與Json的交互,既可用於客戶端,也可用於服務器端
2、既能很好的支持TSession會話方式的基本鑒權,又能很好的支持AccessToken訪問令牌方式或代碼方式的高級鑒權,有專門的非可視化鑒權單元(REST.Authenticator.Basic和REST.Authenticator.OAuth)支持,需要自己寫代碼去實現
弱勢:
如果網絡異常或服務器程序未啟動或服務器程序錯誤,異常,在處理異常方面麻煩一些,其異常類(ERequestError :uses Rest.Types)功能比較簡單!
C:\Program Files (x86)\Embarcadero\Studio\20.0\source\data\rest
RESTClient1: TRESTClient; //uses REST.Client;
RESTRequest1: TRESTRequest; //uses REST.Client;
RESTResponse1: TRESTResponse; //uses REST.Client;
RESTResponseDataSetAdapter1: TRESTResponseDataSetAdapter; /uses REST.Response.Adapter;
REST.BindSource //:Rest客戶端數據綁定源
REST.Utils //:Rest客戶端實用工具:
//:URIEncode、ExtractURLSegmentNames、ExtractGetParams、
//:RESTComponentIsDesigning、TRESTFindDefaultComponent
REST.Authenticator.Basic //:Rest客戶端基本鑒權單元:TSession會話方式
REST.Authenticator.OAuth //:Rest客戶端高級鑒權單元:AccessToken訪問令牌方式或代碼方式
Rest體系的客戶端架構方案:
uses
ClientModuleUnit1, //:我的客戶端數據模塊
Converters
//:我的Json到Bson的互轉類、TBytes到String的互轉類、JSon重新格式化、JSon到delphi代碼轉化、JSon到TJsonWriter代碼轉化、JSon到TJsonBuilder代碼轉化
//:Converters:搜索路徑:D:\PulledupO2O\myPublic\RTL\RTLSamples\Json
, AsyncTask //: 我的異步任務單元
//以下為系統類別:
, System.Types,System.Variants,System.Classes
, System.UITypes
, System.SysUtils,System.IOUtils,System.StartUpCopy
, System.Threading, System.SyncObjs //線程、任務;事件總線
, System.Rtti//:系統運行時刻庫(運行時的類型信息Run Time date Type Infomation):
, System.NetEncoding //:系統網絡編碼的運行時刻庫:編碼加密、解碼解密
, System.Math //:系統數學函數庫
, system.hash //:系統自帶的的Hash哈希單元
, System.Devices //:系統設備描述單元
//系統原生JSON類:
, System.JSON.Types
, System.JSONConsts
, System.JSON.Utils
, System.JSON ,System.JSON.Readers
, System.JSON.Builders
//引用泛型對象*<T>的單元:
//, System.TypInfo ,System.Generics.Collections ,System.Generics.Defaults
//Rest類:
, REST.Response.Adapter, REST.Client //:REST客戶端組件引用: //組件TRESTClient TRESTRequest TRESTResponse TRESTResponseDataSetAdapter的單元:
, REST.Types//:Rest客戶端請求的各種類型的常量、枚舉的定義,異常捕獲的定義
, REST.Consts//:Rest客戶端的運行是提示常量
//Rest的以下體系中這套與Json的交互,既可用於客戶端,也可用於服務器端:
, REST.Json.Types //:REST.Json特殊類型的運行時刻庫:日期、布爾的編組與解析
, REST.Json.Interceptors
//:Json這些數據類型攔截器:實現對時區、日期時間中的分段、
//:數組中的局部字符串:轉TListOfObjects = array of TObject及其反轉
//:字符串中的局部字符串:轉TObject及其反轉
, REST.Json
//:TJson類封裝:將TObject對象轉Json和Json格式的string,
//:Json和Json格式的string轉對象TObject,
//:Json格式化(TStringBuilder規范化重寫)及
//:Json和Json格式的string規范化UTF8編碼
, REST.JsonReflect//:Json映射:數據對象與編組、轉化:
//:REST.JsonReflect來源於Data.DBXJSONReflect,只是它更輕量級.
//:最重要是它不依賴於注入到中JSON對象的元數據.
//:它的目的是“reflect映射”Json屬性到TObject,反之亦然.
//:這里所有JSON對象創建或處理均以“plain”的方式對待.
//在本單元實現方式從設計的觀點來看仍然是“粗糙”的,
//:但會隨着時間的推移得以改善(10.3應該完善啦)
//重要:這里嚴重涉及RTTI,因此可能不能被禁用,必須引用System.RTTI.
//目前不建議直接使用這個單元,因為它的接口可能隨時間而改變.
//:推薦使用REST.Json中的TJson類(或Data.DBXJSONReflect).
//REST.Json中的接口是穩定的.
//:10.0以前暫不建議直接使用它(10.3應該完善啦)
//:可替代方案:使用以下兩個JSon映射互轉的封裝:
//數據庫的JSon映射:數據對象與編組、轉化:
, Data.FireDACJSONReflect ,Data.DBXJSONReflect
, Data.DBXJSONCommon //:數據庫DBX的通用JSON
// 數據庫:字段列表、字段、對象字段、數據鏈接、數據源、字段選項、字段定義列表、索引列表定義:
, Data.DB
//Dbx數據壓縮及過濾器:
, Data.DbxCompressionFilter
//數據綁定單元:
, Data.Bind.Components ,Data.Bind.ObjectScope
官方案例1:
D:\開發測試\Samples\Object Pascal\Database\RESTDemo
C:\Users\Public\Documents\Embarcadero\Studio\20.0\Samples\Object Pascal\Database\RESTDemo
適配JSon數據到客戶端數據集:
官方案例2:
D:\開發測試\Samples\Object Pascal\DataSnap\FireDACJSONReflect\sysClass\source\data\rest\restdebugger\RESTDebugger.dproj
C:\Program Files (x86)\Embarcadero\Studio\20.0\source\data\rest\restdebugger\RESTDebugger.dproj
或者:
2.1、
--->默認值常量:
REST.Types;
TCompletionHandler = TProc;
TCompletionHandlerWithError = TProc<TObject>;
TRESTObjectOwnership = (ooCopy, ooREST, ooApp);
TRESTRequestParameterOption枚舉
TRESTRequestParameterOptions = set of TRESTRequestParameterOption;
TRESTRequestParameterKind枚舉
pkGETorPOST
pkURLSEGMENT
pkREQUESTBODY
pkQUERY
DefaultRESTRequestParameterKind: TRESTRequestParameterKind = TRESTRequestParameterKind.pkGETorPOST;
function RESTRequestParameterKindToString(const AKind: TRESTRequestParameterKind): string;
function RESTRequestParameterKindFromString(const AKindString: string): TRESTRequestParameterKind;
2.2、
type
/// <summary>
/// Content
/// </summary>
TRESTContentType = (ctNone, ctAPPLICATION_ATOM_XML, ctAPPLICATION_ECMASCRIPT, ctAPPLICATION_EDI_X12,
ctAPPLICATION_EDIFACT, ctAPPLICATION_JSON, ctAPPLICATION_JAVASCRIPT, ctAPPLICATION_OCTET_STREAM, ctAPPLICATION_OGG,
ctAPPLICATION_PDF, ctAPPLICATION_POSTSCRIPT, ctAPPLICATION_RDF_XML, ctAPPLICATION_RSS_XML, ctAPPLICATION_SOAP_XML,
ctAPPLICATION_FONT_WOFF, ctAPPLICATION_XHTML_XML, ctAPPLICATION_XML, ctAPPLICATION_XML_DTD, ctAPPLICATION_XOP_XML,
ctAPPLICATION_ZIP, ctAPPLICATION_GZIP, ctTEXT_CMD, ctTEXT_CSS, ctTEXT_CSV, ctTEXT_HTML, ctTEXT_JAVASCRIPT,
ctTEXT_PLAIN, ctTEXT_VCARD, ctTEXT_XML, ctAUDIO_BASIC, ctAUDIO_L24, ctAUDIO_MP4, ctAUDIO_MPEG, ctAUDIO_OGG,
ctAUDIO_VORBIS, ctAUDIO_VND_RN_REALAUDIO, ctAUDIO_VND_WAVE, ctAUDIO_WEBM, ctIMAGE_GIF, ctIMAGE_JPEG, ctIMAGE_PJPEG,
ctIMAGE_PNG, ctIMAGE_SVG_XML, ctIMAGE_TIFF, ctMESSAGE_HTTP, ctMESSAGE_IMDN_XML, ctMESSAGE_PARTIAL, ctMESSAGE_RFC822,
ctMODEL_EXAMPLE, ctMODEL_IGES, ctMODEL_MESH, ctMODEL_VRML, ctMODEL_X3D_BINARY, ctMODEL_X3D_VRML, ctMODEL_X3D_XML,
ctMULTIPART_MIXED, ctMULTIPART_ALTERNATIVE, ctMULTIPART_RELATED, ctMULTIPART_FORM_DATA, ctMULTIPART_SIGNED,
ctMULTIPART_ENCRYPTED, ctVIDEO_MPEG, ctVIDEO_MP4, ctVIDEO_OGG, ctVIDEO_QUICKTIME, ctVIDEO_WEBM, ctVIDEO_X_MATROSKA,
ctVIDEO_X_MS_WMV, ctVIDEO_X_FLV, ctAPPLICATION_VND_OASIS_OPENDOCUMENT_TEXT,
ctAPPLICATION_VND_OASIS_OPENDOCUMENT_SPREADSHEET, ctAPPLICATION_VND_OASIS_OPENDOCUMENT_PRESENTATION,
ctAPPLICATION_VND_OASIS_OPENDOCUMENT_GRAPHICS, ctAPPLICATION_VND_MS_EXCEL,
ctAPPLICATION_VND_OPENXMLFORMATS_OFFICEDOCUMENT_SPREADSHEETML_SHEET, ctAPPLICATION_VND_MS_POWERPOINT,
ctAPPLICATION_VND_OPENXMLFORMATS_OFFICEDOCUMENT_PRESENTATIONML_PRESENTATION,
ctAPPLICATION_VND_OPENXMLFORMATS_OFFICEDOCUMENT_WORDPROCESSINGML_DOCUMENT, ctAPPLICATION_VND_MOZILLA_XUL_XML,
ctAPPLICATION_VND_GOOGLE_EARTH_KML_XML, ctAPPLICATION_VND_GOOGLE_EARTH_KMZ, ctAPPLICATION_VND_DART,
ctAPPLICATION_VND_ANDROID_PACKAGE_ARCHIVE, ctAPPLICATION_X_DEB, ctAPPLICATION_X_DVI, ctAPPLICATION_X_FONT_TTF,
ctAPPLICATION_X_JAVASCRIPT, ctAPPLICATION_X_LATEX, ctAPPLICATION_X_MPEGURL, ctAPPLICATION_X_RAR_COMPRESSED,
ctAPPLICATION_X_SHOCKWAVE_FLASH, ctAPPLICATION_X_STUFFIT, ctAPPLICATION_X_TAR, ctAPPLICATION_X_WWW_FORM_URLENCODED,
ctAPPLICATION_X_XPINSTALL, ctAUDIO_X_AAC, ctAUDIO_X_CAF, ctIMAGE_X_XCF, ctTEXT_X_GWT_RPC, ctTEXT_X_JQUERY_TMPL,
ctTEXT_X_MARKDOWN, ctAPPLICATION_X_PKCS12, ctAPPLICATION_X_PKCS7_CERTIFICATES, ctAPPLICATION_X_PKCS7_CERTREQRESP,
ctAPPLICATION_X_PKCS7_MIME, ctAPPLICATION_X_PKCS7_SIGNATURE, ctAPPLICATION_VND_EMBARCADERO_FIREDAC_JSON);
var
DefaultRESTContentType: TRESTContentType = TRESTContentType.ctNone;
const
/// <summary>
/// HTTP Content-Type (or MIME Types as per RFC 2046) header Definitions.
/// </summary>
/// <remarks>
/// <para>
/// See: http://tools.ietf.org/html/rfc2046
/// </para>
/// <para>
/// Values collected from https://en.wikipedia.org/wiki/MIME_type
/// </para>
/// </remarks>
CONTENTTYPE_NONE = ''; // do not localize
// Type Application
CONTENTTYPE_APPLICATION_ATOM_XML = 'application/atom+xml'; // do not localize
CONTENTTYPE_APPLICATION_ECMASCRIPT = 'application/ecmascript'; // do not localize
CONTENTTYPE_APPLICATION_EDI_X12 = 'application/EDI-X12'; // do not localize
CONTENTTYPE_APPLICATION_EDIFACT = 'application/EDIFACT'; // do not localize
CONTENTTYPE_APPLICATION_JSON = 'application/json'; // do not localize
CONTENTTYPE_APPLICATION_JAVASCRIPT = 'application/javascript'; // do not localize
CONTENTTYPE_APPLICATION_OCTET_STREAM = 'application/octet-stream'; // do not localize
CONTENTTYPE_APPLICATION_OGG = 'application/ogg'; // do not localize
CONTENTTYPE_APPLICATION_PDF = 'application/pdf'; // do not localize
CONTENTTYPE_APPLICATION_POSTSCRIPT = 'application/postscript'; // do not localize
CONTENTTYPE_APPLICATION_RDF_XML = 'application/rdf+xml'; // do not localize
CONTENTTYPE_APPLICATION_RSS_XML = 'application/rss+xml'; // do not localize
CONTENTTYPE_APPLICATION_SOAP_XML = 'application/soap+xml'; // do not localize
CONTENTTYPE_APPLICATION_FONT_WOFF = 'application/font-woff'; // do not localize
CONTENTTYPE_APPLICATION_XHTML_XML = 'application/xhtml+xml'; // do not localize
CONTENTTYPE_APPLICATION_XML = 'application/xml'; // do not localize
CONTENTTYPE_APPLICATION_XML_DTD = 'application/xml-dtd'; // do not localize
CONTENTTYPE_APPLICATION_XOP_XML = 'application/xop+xml'; // do not localize
CONTENTTYPE_APPLICATION_ZIP = 'application/zip'; // do not localize
CONTENTTYPE_APPLICATION_GZIP = 'application/gzip'; // do not localize
// Type Text
CONTENTTYPE_TEXT_CMD = 'text/cmd'; // do not localize
CONTENTTYPE_TEXT_CSS = 'text/css'; // do not localize
CONTENTTYPE_TEXT_CSV = 'text/csv'; // do not localize
CONTENTTYPE_TEXT_HTML = 'text/html'; // do not localize
CONTENTTYPE_TEXT_JAVASCRIPT = 'text/javascript'; // do not localize
CONTENTTYPE_TEXT_PLAIN = 'text/plain'; // do not localize
CONTENTTYPE_TEXT_VCARD = 'text/vcard'; // do not localize
CONTENTTYPE_TEXT_XML = 'text/xml'; // do not localize
// Type Audio
CONTENTTYPE_AUDIO_BASIC = 'audio/basic'; // do not localize
CONTENTTYPE_AUDIO_L24 = 'audio/L24'; // do not localize
CONTENTTYPE_AUDIO_MP4 = 'audio/mp4'; // do not localize
CONTENTTYPE_AUDIO_MPEG = 'audio/mpeg'; // do not localize
CONTENTTYPE_AUDIO_OGG = 'audio/ogg'; // do not localize
CONTENTTYPE_AUDIO_VORBIS = 'audio/vorbis'; // do not localize
CONTENTTYPE_AUDIO_VND_RN_REALAUDIO = 'audio/vnd.rn-realaudio'; // do not localize
CONTENTTYPE_AUDIO_VND_WAVE = 'audio/vnd.wave'; // do not localize
CONTENTTYPE_AUDIO_WEBM = 'audio/webm'; // do not localize
// Type Image
CONTENTTYPE_IMAGE_GIF = 'image/gif'; // do not localize
CONTENTTYPE_IMAGE_JPEG = 'image/jpeg'; // do not localize
CONTENTTYPE_IMAGE_PJPEG = 'image/pjpeg'; // do not localize
CONTENTTYPE_IMAGE_PNG = 'image/png'; // do not localize
CONTENTTYPE_IMAGE_SVG_XML = 'image/svg+xml'; // do not localize
CONTENTTYPE_IMAGE_TIFF = 'image/tiff'; // do not localize
// Type Message
CONTENTTYPE_MESSAGE_HTTP = 'message/http'; // do not localize
CONTENTTYPE_MESSAGE_IMDN_XML = 'message/imdn+xml'; // do not localize
CONTENTTYPE_MESSAGE_PARTIAL = 'message/partial'; // do not localize
CONTENTTYPE_MESSAGE_RFC822 = 'message/rfc822'; // do not localize
// Type Model (3D Models)
CONTENTTYPE_MODEL_EXAMPLE = 'model/example'; // do not localize
CONTENTTYPE_MODEL_IGES = 'model/iges'; // do not localize
CONTENTTYPE_MODEL_MESH = 'model/mesh'; // do not localize
CONTENTTYPE_MODEL_VRML = 'model/vrml'; // do not localize
CONTENTTYPE_MODEL_X3D_BINARY = 'model/x3d+binary'; // do not localize
CONTENTTYPE_MODEL_X3D_VRML = 'model/x3d+vrml'; // do not localize
CONTENTTYPE_MODEL_X3D_XML = 'model/x3d+xml'; // do not localize
// Type Multipart
CONTENTTYPE_MULTIPART_MIXED = 'multipart/mixed'; // do not localize
CONTENTTYPE_MULTIPART_ALTERNATIVE = 'multipart/alternative'; // do not localize
CONTENTTYPE_MULTIPART_RELATED = 'multipart/related'; // do not localize
CONTENTTYPE_MULTIPART_FORM_DATA = 'multipart/form-data'; // do not localize
CONTENTTYPE_MULTIPART_SIGNED = 'multipart/signed'; // do not localize
CONTENTTYPE_MULTIPART_ENCRYPTED = 'multipart/encrypted'; // do not localize
// Type Video
CONTENTTYPE_VIDEO_MPEG = 'video/mpeg'; // do not localize
CONTENTTYPE_VIDEO_MP4 = 'video/mp4'; // do not localize
CONTENTTYPE_VIDEO_OGG = 'video/ogg'; // do not localize
CONTENTTYPE_VIDEO_QUICKTIME = 'video/quicktime'; // do not localize
CONTENTTYPE_VIDEO_WEBM = 'video/webm'; // do not localize
CONTENTTYPE_VIDEO_X_MATROSKA = 'video/x-matroska'; // do not localize
CONTENTTYPE_VIDEO_X_MS_WMV = 'video/x-ms-wmv'; // do not localize
CONTENTTYPE_VIDEO_X_FLV = 'video/x-flv'; // do not localize
// Type Application - Vendor Specific
CONTENTTYPE_APPLICATION_VND_OASIS_OPENDOCUMENT_TEXT = 'application/vnd.oasis.opendocument.text'; // do not localize
CONTENTTYPE_APPLICATION_VND_OASIS_OPENDOCUMENT_SPREADSHEET = 'application/vnd.oasis.opendocument.spreadsheet';
// do not localize
CONTENTTYPE_APPLICATION_VND_OASIS_OPENDOCUMENT_PRESENTATION = 'application/vnd.oasis.opendocument.presentation';
// do not localize
CONTENTTYPE_APPLICATION_VND_OASIS_OPENDOCUMENT_GRAPHICS = 'application/vnd.oasis.opendocument.graphics';
// do not localize
CONTENTTYPE_APPLICATION_VND_MS_EXCEL = 'application/vnd.ms-excel'; // do not localize
CONTENTTYPE_APPLICATION_VND_OPENXMLFORMATS_OFFICEDOCUMENT_SPREADSHEETML_SHEET =
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'; // do not localize
CONTENTTYPE_APPLICATION_VND_MS_POWERPOINT = 'application/vnd.ms-powerpoint'; // do not localize
CONTENTTYPE_APPLICATION_VND_OPENXMLFORMATS_OFFICEDOCUMENT_PRESENTATIONML_PRESENTATION =
'application/vnd.openxmlformats-officedocument.presentationml.presentation'; // do not localize
CONTENTTYPE_APPLICATION_VND_OPENXMLFORMATS_OFFICEDOCUMENT_WORDPROCESSINGML_DOCUMENT =
'application/vnd.openxmlformats-officedocument.wordprocessingml.document'; // do not localize
CONTENTTYPE_APPLICATION_VND_MOZILLA_XUL_XML = 'application/vnd.mozilla.xul+xml'; // do not localize
CONTENTTYPE_APPLICATION_VND_GOOGLE_EARTH_KML_XML = 'application/vnd.google-earth.kml+xml'; // do not localize
CONTENTTYPE_APPLICATION_VND_GOOGLE_EARTH_KMZ = 'application/vnd.google-earth.kmz'; // do not localize
CONTENTTYPE_APPLICATION_VND_DART = 'application/vnd.dart'; // do not localize
CONTENTTYPE_APPLICATION_VND_ANDROID_PACKAGE_ARCHIVE = 'application/vnd.android.package-archive'; // do not localize
// Type X (RFC 6648)
CONTENTTYPE_APPLICATION_X_DEB = 'application/x-deb'; // do not localize
CONTENTTYPE_APPLICATION_X_DVI = 'application/x-dvi'; // do not localize
CONTENTTYPE_APPLICATION_X_FONT_TTF = 'application/x-font-ttf'; // do not localize
CONTENTTYPE_APPLICATION_X_JAVASCRIPT = 'application/x-javascript'; // do not localize
CONTENTTYPE_APPLICATION_X_LATEX = 'application/x-latex'; // do not localize
CONTENTTYPE_APPLICATION_X_MPEGURL = 'application/x-mpegURL'; // do not localize
CONTENTTYPE_APPLICATION_X_RAR_COMPRESSED = 'application/x-rar-compressed'; // do not localize
CONTENTTYPE_APPLICATION_X_SHOCKWAVE_FLASH = 'application/x-shockwave-flash'; // do not localize
CONTENTTYPE_APPLICATION_X_STUFFIT = 'application/x-stuffit'; // do not localize
CONTENTTYPE_APPLICATION_X_TAR = 'application/x-tar'; // do not localize
CONTENTTYPE_APPLICATION_X_WWW_FORM_URLENCODED = 'application/x-www-form-urlencoded'; // do not localize
CONTENTTYPE_APPLICATION_X_XPINSTALL = 'application/x-xpinstall'; // do not localize
CONTENTTYPE_AUDIO_X_AAC = 'audio/x-aac'; // do not localize
CONTENTTYPE_AUDIO_X_CAF = 'audio/x-caf'; // do not localize
CONTENTTYPE_IMAGE_X_XCF = 'image/x-xcf'; // do not localize
CONTENTTYPE_TEXT_X_GWT_RPC = 'text/x-gwt-rpc'; // do not localize
CONTENTTYPE_TEXT_X_JQUERY_TMPL = 'text/x-jquery-tmpl'; // do not localize
CONTENTTYPE_TEXT_X_MARKDOWN = 'text/x-markdown'; // do not localize
// Type PKCS (Cryptography)
CONTENTTYPE_APPLICATION_X_PKCS12 = 'application/x-pkcs12'; // do not localize
CONTENTTYPE_APPLICATION_X_PKCS7_CERTIFICATES = 'application/x-pkcs7-certificates'; // do not localize
CONTENTTYPE_APPLICATION_X_PKCS7_CERTREQRESP = 'application/x-pkcs7-certreqresp'; // do not localize
CONTENTTYPE_APPLICATION_X_PKCS7_MIME = 'application/x-pkcs7-mime'; // do not localize
CONTENTTYPE_APPLICATION_X_PKCS7_SIGNATURE = 'application/x-pkcs7-signature'; // do not localize
// Type Application - Embarcadero Specific
CONTENTTYPE_APPLICATION_VND_EMBARCADERO_FIREDAC_JSON = 'application/vnd.embarcadero.firedac+json'; // do not localize
function ContentTypeToString(AContentType: TRESTContentType): string;
function ContentTypeFromString(const AContentType: string): TRESTContentType;
function IsTextualContentType(AContentType: TRESTContentType) : boolean; overload;
function IsTextualContentType(const AContentType: string) : boolean; overload;
2.3、
TRESTRequestMethod枚舉
rmPOST
rmPUT
rmGET
rmDELETE
rmPATCH
--->
const
sRequestDefaultAccept = CONTENTTYPE_APPLICATION_JSON + ', ' +
CONTENTTYPE_TEXT_PLAIN + '; q=0.9, ' + CONTENTTYPE_TEXT_HTML + ';q=0.8,';
// UTF-8 is prefered, any other is good, but marked down:
sRequestDefaultAcceptCharset = 'utf-8, *;q=0.8';
sDefaultFallbackCharSetEncoding = 'utf-8';
sDefaultUserAgent = 'Embarcadero RESTClient/' + RESTCLIENT_VERSION;
sBody = 'body';
sFile = 'file';
2.4、
RESTRequest.ResetToDefaults;
Method := DefaultRESTRequestMethod;
Resource := '';
ResourceSuffix := '';
Timeout := 30000; // Some servers may be slow. Esp if they just recycled and need to start up on their first request
Accept := sRequestDefaultAccept;
AcceptCharset := sRequestDefaultAcceptCharset;
HandleRedirects := True;
FExecutionPerformance.Clear;
FURLAlreadyEncoded := False;
FParams.Clear;
FTransientParams.Clear;
FBody.ClearBody;
if FClient <> nil then
FClient.ContentType := '';
if FResponse <> nil then
FResponse.ResetToDefaults;
// we intentionally do not reset "FAutoCreateParams"
var
DefaultRESTRequestMethod: TRESTRequestMethod = TRESTRequestMethod.rmGET;
function RESTRequestMethodToString(const AMethod: TRESTRequestMethod): string;
RESTClient.ResetToDefaults;
CreateHttpClient;
BaseURL := '';
ProxyServer := '';
ProxyPort := 0;
ProxyUsername := '';
ProxyPassword := '';
UserAgent := sDefaultUserAgent;
FallbackCharsetEncoding := sDefaultFallbackCharSetEncoding;
FSynchronizedEvents := True;
FRaiseExceptionOn500 := True;
FAutoCreateParams := True;
FParams.Clear;
FTransientParams.Clear;
RESTResponse.ResetToDefaults;
RESTResponseDataSetAdapter.ResetToDefaults;
--->
TRESTResponse = class(TCustomRESTResponse)
published
property Content;
property ContentLength;
property ContentType;
property ContentEncoding;
property RootElement;
property BindSource;
end;
2.5、 TRESTClient = class(TCustomRESTClient)
published
property Authenticator;
property Accept;
property AcceptCharset;
property AcceptEncoding;
property AllowCookies;
property AutoCreateParams;
property BaseURL;
property ContentType;
property FallbackCharsetEncoding;
property Params;
property HandleRedirects;
property RedirectsWithGET;
property SecureProtocols;
property ProxyPassword;
property ProxyPort;
property ProxyServer;
property ProxyUsername;
property RaiseExceptionOn500;
property SynchronizedEvents;
property UserAgent;
property OnHTTPProtocolError;
property BindSource;
property OnValidateCertificate;
property OnNeedClientCertificate;
property OnAuthEvent;
end;
2.6、 //以流的方式下載1個文件: Download a file
TDownloadURL = class
private
class procedure CheckForError(const AResponse: TCustomRESTResponse); static;
public
class procedure DownloadRawBytes(const AURL: string; const AStream: TStream); static;
end;
2.7、 TRESTRequest在執行時,如果網絡異常或服務器程序未啟動或服務器程序錯誤,異常,在處理異常方面麻煩一些,其異常類(ERequestError :uses Rest.Types)功能比較簡單!
2.8、 TRESTRequest同步執行模式:
provedure TCustomRESTRequest.Execute;
2.9、 TRESTRequest異步執行模式:
function TCustomRESTRequest.ExecuteAsync(
ACompletionHandler: TCompletionHandler = nil;
ASynchronized: boolean = True;
AFreeThread: boolean = True;
ACompletionHandlerWithError: TCompletionHandlerWithError = nil
): TRESTExecutionThread;
Executes a request asynchronously, i.e. run it in its own thread. There is no automatic serialization op
property access though, which means that while the execution thread runs, properties of all involved
TCustomRESTClient and TCustomRESTRequest instances should not be touched from other threads (including the main thread)
Using ExecuteAsync is strongly recommended on mobile platforms. iOS (and likely Android) will
terminate an application if it considers the main thread to be unresponsive, which would be the case if
there is a running request which takes more than a second or two to return.
執行異步請求,即在自己的線程中運行它。沒有自動序列化op
屬性訪問,這意味着在執行線程運行時,所有相關的屬性
TCustomRESTClient和TCustomRESTRequest實例不應該觸及從其他線程(包括主線程)
移動平台上使用ExecuteAsync是強烈推薦。iOS(和可能Android)
終止應用程序如果認為主線程是反應遲鈍,如果這將是如此
有一個請求,需要超過一兩秒鍾返回。
摘要說明:
The idea behind this is that the UI runs in the main thread and mobile devices should respond to user
interaction basically immediately. Sluggish behaviour (caused by blocking the main thread) is considered
unacceptable on these small devices.
背后的想法是,用戶界面運行在主線程和移動設備應該響應用戶
互動基本上立即。緩慢的行為(阻塞主線程所致)
這些小設備上不可接受。
參數: name=ARequest
The request to be executed 要執行的請求
:參數結束
參數: name=ACompletionHandler
An anonymous method that will be run after the execution completed
execute執行完成后的1個一個匿名方法
參數: name=ASynchronized
Specifies if ACompletioHandler will be run in the main thread's (True) or execution thread's (False) context
如果指定了ACompletioHandler,它將運行在主線程(True),否則它在執行線程的上下文運行(False)
參數: name=AFreeThread
If True, then the execution thread will be freed after it completed
如果True,那么運行完成后執行線程將被釋放
參數: name=ACompletionHandlerWithError
An anonymous method that will be run if an exception is raised during execution
在執行期間如果拋出異常,這個一個匿名方法將被執行
返回值:
Returns a reference to the execution thread. Should only be used if AFreeThread=False,
as other wise the reference may get invalid unexpectedly.
返回對執行線程的引用。只用於參數AFreeThread = False,否則
返回的這個引用可能會意外的無效。
2.10、應用案例:
///<summary>系統REST.Client單元Rest請求Web服務並返回Json數據:</summary>
/// <param name="AParams">:參數:RESTRequest的請求參數名的動態數組:TArray[system.string]即:TStringDynArray: 參考:System.IOUtils下的函數的初始化及實現方法:TDirectory.DoGetFiles.</param>
/// <param name="AParamsValue">:參數:RESTRequest的請求參數值的動態數組.</param>
/// <param name="ABaseUrl">:參數:RESTClient的URL資源的位置:即URL的第1段:BaseUrl://:最后1個"/"可帶可不帶:比如:http://www.cpuofbs.com:8080/或http://www.cpuofbs.com:8080均可:
///但不能重復"/":http://www.cpuofbs.com:8080//是錯誤的.
/// </param>
/// <param name="AResource">:參數:RESTRequest的服務器端方法函數(函數名及其參數名列表):即URL的第2段:Resource,比如:'getRecCountOnContitions/{pWhereGroupHavingEtc}/{pDataObject}'
///前綴"/"可帶可不帶:比如:getRecCountOnContitions/{pWhereGroupHavingEtc}/{pDataObject}
///或/getRecCountOnContitions/{pWhereGroupHavingEtc}/{pDataObject}'均可:前綴"/"可重復.
///每個參數名需要用{}括起來; 多個參數名用"/"分割開來。
///若用瀏覽器地址顯式的rmGET數據,使用參數的數值而非參數名,表達為比如:http://www.cpuofbs.com:8080/datasnap/rest/TServerMethods1/getRecCountOnContitions/where (1=1)/PosBill
/// </param>
/// <param name="AMethod">:參數:RESTRequest的請求服務器端資源的類型(方法):uses REST.Types:rmPOST發送對象到服務器 rmPUT更新已存在或發送新的服務器對象
///rmGET檢索並取回服務器對象 rmDELETE刪除服務器已尋在對象 rmPATCH打補丁更新服務器上的Jsonpairs.
/// </param>
/// <param name="ModeAsyncOrSync">:參數:RESTRequest的請求執行的同步或異步模式:
///:=Async異步模式(默認);=sync同步模式
/// </param>
/// <param name="ADialogService">:參數:為主線程傳入1個對話框服務提供主線程調用:
///:=(默認nil)
/// </param>
/// <returns>:返回值:RESTRequest服務器端的方法返回的JSonValue:</returns>
function RestWebService(
var AParams:TArray<system.string>;//:即:TStringDynArray: 參考:System.IOUtils下的函數的初始化及實現方法:TDirectory.DoGetFiles
var AParamsValue:TArray<system.string>;
const ABaseUrl:string='';
AResource:string='';
AMethod:TRESTRequestMethod=rmGET;
const ModeAsyncOrSync:string='Async';
const ADialogService:TDialogService=nil
):string;//:返回的JSon作為String后需要解析
implemention
function RestWebService(
var AParams:TArray<system.string>;//:即:TStringDynArray: 參考:System.IOUtils下的函數的初始化及實現方法:TDirectory.DoGetFiles
var AParamsValue:TArray<system.string>;
const ABaseUrl:string='';
AResource:string='';
AMethod:TRESTRequestMethod=rmGET;
const ModeAsyncOrSync:string='Async';
const ADialogService:TDialogService=nil
):string;//:返回的JSon作為String后需要解析
var
LRESTClient: TRESTClient;
LRESTRequest: TRESTRequest;
LRESTResponse: TRESTResponse;
LParamsCount:Integer;
LEncoding:TEncoding;
LResultStr:string;
LTWaitResult:Cardinal;
LThread:TThread;
LRestReqErr:ERequestError; //:異常類:uses Rest.Types
LRestReqStatusCode:Integer; //:異常響應狀態碼:默認0:正常值200
LRestReqStatusText:string; //:異常響應狀態文本:默認''
begin
//1、判斷參數的完整性和一致性:
if (ABaseUrl.Trim='')
or (AResource.Trim='')
or (Length(AParams)<>Length(AParamsValue))
or ( (UpperCase(ModeAsyncOrSync)<>'ASYNC')
and (UpperCase(ModeAsyncOrSync)<>'SYNC') ) then
begin
Result:='';
Exit;
end;
//2、設置Rest組件參數:
LRESTClient:= TRESTClient.Create(nil);
LRESTClient.ResetToDefaults;
LRESTClient.BaseURL:=ABaseUrl;//:重要 :設置服務器方法的資源位置
LRESTResponse:= TRESTResponse.Create(nil);
LRESTResponse.ResetToDefaults;
//LRESTResponse.ContentType:='application/json';
LRESTRequest:= TRESTRequest.Create(nil);
LRESTRequest.ResetToDefaults;
LRESTRequest.Client:=LRESTClient;
LRESTRequest.Method:=AMethod;
//LRESTRequest.SynchronizedEvents:=false;//:不要同步事件
LRESTRequest.Resource:=AResource;//:重要:設置請求RESTRequest的服務器方法資源:方法函數名
LRESTRequest.Response:=LRESTResponse;
if Length(AParams)>0 then //:如果有參數
begin
LRESTRequest.Params.Clear;
LEncoding:=TEncoding.GetEncoding('UTF8');
for LParamsCount := 0 to Length(AParams)-1 do
begin //重要:設置請求RESTRequest的參數(如果有的話):
AParams[LParamsCount]:=LEncoding.GetString(LEncoding.GetBytes(AParams[LParamsCount]));
AParamsValue[LParamsCount]:=LEncoding.GetString(LEncoding.GetBytes(AParamsValue[LParamsCount]));
//:2.1、請求方法Method為POST時:TRESTRequestMethod.rmPOST
//:若參數及其參數值含中文
//:應當將參數及其參數值TEncoding.UTF8:
//:或:
//AParams[LParamsCount]:=TIdURI.ParamsEncode(AParams[LParamsCount], IndyTextEncoding_UTF8);
//:TIdURI: uses IdURI ;IndyTextEncoding_UTF8: uses IdGlobal
//:2.2、請求參數數值應與被調用的服務器函數的參數類型相一致:
//:為簡便易用,服務器函數的參數約定均設置成string:
//:便於處理TDatetime和Boolean數據類型
LRESTRequest.AddParameter(
AParams[LParamsCount],
AParamsValue[LParamsCount],
pkURLSEGMENT);
end;
end;
//3、執行Rest請求RESTRequest並返回響應結果RESTResponse:
//異步執行案例:
if UpperCase(ModeAsyncOrSync)='ASYNC' then
begin
LThread:=(
LRESTRequest.ExecuteAsync(
procedure
begin
LResultStr:=LRESTResponse.Content;
//產生請求異常的響應結果:
LRestReqStatusCode:=200; //:正確的返回
LRestReqStatusText:='OK';//:正確的返回
LRestReqErr:=ERequestError.Create(LRestReqStatusCode,LRestReqStatusText,LResultStr);
end,
true,
false, //:釋放執行線程
procedure (ExceptionObject:TObject) //Sender:TObject
begin //異常:
if LRestReqStatusCode<>200 then //:如果請求返回異常的響應狀態碼
if ExceptionObject is Exception then
LResultStr:='{"result":['+IntToStr(LRestReqStatusCode)+']}';
//代表:'請求的資源或參數錯誤'導致不返回任何結果;
//LResultStr:='{"result":[0]}';//代表:'請求的資源或參數錯誤'導致不返回任何結果;
//Application.ProcessMessages;
//raise Exception.Create('請求的資源或參數錯誤');
//:異常捕獲類:ERESTException:Exception:uses REST.Types
//:常規方法:捕獲不了異常,只能通過上述ERESTException.StatusCode傳給
//:LResultStr傳遞的返回值給客戶端主線程來提示
end
) as TThread);
LTWaitResult:=LThread.WaitFor; //TWaitResult
if LTWaitResult=0 then
begin
Result:=LResultStr;//:返回Json格式字符串
//4、釋放Rest組件:
LRESTClient.Free;
LRESTRequest.Free;
LRESTResponse.Free;
LEncoding.Free;
LThread.Free;
end else
begin
{
Application.ProcessMessages;
raise Exception.Create('請求的資源或參數錯誤');
//:異常捕獲不了,只能通過返回值給客戶端主線程來提示
//:故而此段代碼無意義!
Result:=LResultStr;//:返回Json格式字符串
//4、釋放Rest組件:
LRESTClient.Free;
LRESTRequest.Free;
LRESTResponse.Free;
LEncoding.Free;
LThread.Free;
}
end;
end else
if UpperCase(ModeAsyncOrSync)='SYNC' then
begin //同步執行:
try
try
LRESTRequest.Execute;
LResultStr:=LRESTResponse.Content;
//產生請求異常的響應結果:
LRestReqStatusCode:=200; //:正確的返回
LRestReqStatusText:='OK';//:正確的返回
LRestReqErr:=ERequestError.Create(LRestReqStatusCode,LRestReqStatusText,LResultStr);
except
if LRestReqStatusCode<>200 then //:如果請求返回異常的響應狀態碼
if ExceptionObject is Exception then
LResultStr:='{"result":['+IntToStr(LRestReqStatusCode)+']}';
//代表:'請求的資源或參數錯誤'導致不返回任何結果;
//LResultStr:='{"result":[0]}';//代表:'請求的資源或參數錯誤'導致不返回任何結果;
//Application.ProcessMessages;
//raise Exception.Create('請求的資源或參數錯誤');
//:異常捕獲類:ERESTException:Exception:uses REST.Types
//:常規方法:捕獲不了異常,只能通過上述ERESTException.StatusCode傳給
//:LResultStr傳遞的返回值給客戶端主線程來提示
end;
finally
Result:=LResultStr;//:返回Json格式字符串
//4、釋放Rest組件:
LRESTClient.Free;
LRESTRequest.Free;
LRESTResponse.Free;
LEncoding.Free;
LRestReqErr.Free;
end;
end;
//其它說明:
//REST.Client控件從服務器Rest獲得數據集到客戶端適配數據集:
//LRESTResponseDataSetAdapter.Response:= LRESTResponse;
//LRESTResponseDataSetAdapter.Dataset:= LFDMemTable;
end;
2.11、調用方法:
procedure TfmxRestAndRestJson.Label5Click(Sender: TObject);
//Rest記錄數: https://www.cpuofbs.com:8080/datasnap/rest/TServerMethods1/getRecCountOnContitions/PosBill/where (1=1)
var
LResponseContent:string;
LRecordCount:Integer;
LJO:TJsonObject;
AParams:TArray<system.string>;//:即:TStringDynArray;
AParamsValue:TStringDynArray;
begin
TabControl1.ActiveTab:=TabItem1;
LRecordCount:=0;
//TArray<system.string>動態數組初始化的方法:
AParams := nil; AParamsValue := nil;
SetLength(AParams,2);
SetLength(AParamsValue,2);
//:動態數組不設置長度進行賦值會報錯:
AParams[0]:='ATableOrViewName';
AParams[1]:='ASqlWhereEtc';
AParamsValue[0]:='PosBill';
AParamsValue[1]:='where (1=1)';//'where (corp_name=''張尚書_廠部'')';
try
try
LResponseContent:=
RestWebService(
AParams,
AParamsValue,
'https://www.cpuofbs.com:8080/datasnap/rest/TServerMethods1/',
//:最后"/"個/可帶可不帶
'/getRecCountOnContitions/{ATableOrViewName}/{ASqlWhereEtc}',
//:前綴"/"可帶可不帶
TRESTRequestMethod.rmGET,
//:請求方式TRESTRequestMethod不同於請求參數的種類:
//TRESTRequestParameterKind.pkGETorPOST TRESTRequestParameterKind.pkURLSEGMENT
'sync'
); //:uses myFuc_Client;
except
AParams := nil; AParamsValue := nil;
raise Exception.Create('請求的資源或參數錯誤');
end;
finally
//:對上述返回udeRESTResponse.Content解析:
LJO:=(TJsonObject.ParseJSONValue(LResponseContent) as TJsonObject);
try
LRecordCount:=(( LJO.GetValue('result') as TJsonArray).Items[0] as TJsonNumber).AsInt;
finally
LJO.Free;
end;
Memo1.Lines.Clear;
Memo1.Lines.BeginUpdate;
Memo1.Lines.Add('Rest響應內容:'+LResponseContent);
Memo1.Lines.Add('記錄數:'+IntToStr(LRecordCount));
Memo1.Lines.EndUpdate;
end;
end;
執行結果:
若服務未啟動或網絡異常:
三、Indy技術體系: IdHTTP; IdFTP; IdSSLOpenSSL; IdCookieManager; IdCompressorZLib; IdInterceptThrottler; IdInterceptSimLog;
非DX原生的:來源於第三方Indy
依賴:組件及其提供方的OEM開發工具的版本。依賴於不同操作系統下的庫文件(libeay32、ssleay32;libeay64、ssleay64;libssl.so、libcrypto.so;libssl.a、libcrypto.a)的更新:WIndows 下的.dll動態庫文件,Android下的.so庫文件,IOS下.a靜態庫文件,而且還需要分區32位及64位操作系統下不同的庫文件
適用於:1、服務器端Https服務的第三方SSL證書的導入和驗證,2、服務器端的SSL客制化證書的生成和簽發
弱勢:跨平台客戶端的SSL驗證和Https訪問,可以用,但需分平台且受制組件的版本,分發(發布)時較麻煩而已!
優勢:資格最老的網絡組件提供商,協議層很強大(是delphi Datasnap (Rest)Server的Web.HTTPApp(協議)、Web.WebReq(web請求)、Web.WebBroker(web代理)的橋接底層,其它不依賴它);網絡方面技術面面俱到,類庫龐大,一直為delphi內置組件庫
IdSSLIOHandlerSocketOpenSSL1: TIdSSLIOHandlerSocketOpenSSL; //: 處理https(協議層)的OpenSSL的方式
IdInterceptThrottler1: TIdInterceptThrottler;
IdInterceptSimLog1: TIdInterceptSimLog;
IdCookieManager1: TIdCookieManager;
IdCompressorZLib1: TIdCompressorZLib; //: 處理壓縮解壓
C:\Program Files (x86)\Embarcadero\Studio\20.0\source\Indy10\Protocols
案例1: D:\delphiXEDev\HttpUpLoadAndDownLoad\IdHttpDownLoad
案例2: D:\delphiXEDev\OpenSSL\OpenSSL-delphi編程Https\delphi編程HttpsDownload\Win64\Debug
網頁數據抓取(抓包、網頁爬取、爬蟲):
四、瀏覽器客戶端技術JavaScript+jQuery(Mobile)+Http DOM+Ajax
非常強大,目前主流技術!
跨平台、跨操作系統、跨語言
4.1、篇幅所限,不再贅述!學習的話,可參考:
(以下轉,感謝博主!)
最權威:官方產品經理:Marco Cantù的 《REST Servers in Delphi XE Using DataSnap》,網上的中文翻譯版.pdf :
https://download.csdn.net/download/weixin_42404994/10742572
《REST Servers in Delphi XE Using DataSnap》源碼下載:REST Servers in Delphi XE Using DataSnap.CodeSample.rar
https://download.csdn.net/download/chunyangsuhao/11429142
Delphi 10.3 Web應用開發B/S框架介紹(一):uniGUI:
https://blog.csdn.net/xyzhan/article/details/86527802
Delphi 10.3 Web應用開發B/S框架介紹(二):IntraWeb 17:
https://blog.csdn.net/xyzhan/article/details/86528302
Bootstrap中文版(響應式):
Bootstrap+H5+Css3+js網頁前端可視化布局在線生成工具:
https://www.bootcss.com/p/layoutit/
w3school:Web前端技術學習大全:
https://www.w3school.com.cn/index.html 其中內容如下:
HTML及H5+CSS3教程 + 瀏覽器腳本 + 服務器腳本 + XML教程
其中,瀏覽器腳本:
JavaScript、HTML DOM、jQuery、jQuery Mobile、AJAX、JSON、DHTML、E4X、WMLScript
4.2、附:delphi App中調用JavaScript方法,供學習參考::
(以下轉,感謝博主!)
基於HTML模板和JSON數據的JavaScript交互:
https://blog.csdn.net/u013558749/article/details/52445049
REST Datasnap服務端與javascript客戶端實現:
https://blog.csdn.net/a00553344/article/details/51719643
delphi與javascript交互:
https://download.csdn.net/download/qq_30347073/9162031
解決Delphi(FireMonkey)Andorid,IOS移動應用WebBrowser與JavaScript交互問題:
http://blog.sina.com.cn/s/blog_72eb56aa0102xkgg.html
Firemonkey擴展增強:Android 瀏覽器執行JavaScript獲取結果及JavaScript調用本地方法:
https://blog.csdn.net/tht2009/article/details/53996177
Windows下:
Delphi 中調用JS文件中的方法:
https://www.cnblogs.com/limingliyu/p/5658767.html
delphi中執行javascript代碼:
http://www.delphitop.com/html/wenjian/2780.html
4.3、其它:
JS清除緩存的幾種方法:
https://blog.csdn.net/weixin_42983021/article/details/92833944