使用 TRESTClient 与 TRESTRequest 作为 HTTP Client(转)

时间:2022-09-22 08:57:14

使用 TRESTClient 与 TRESTRequest 作为 HTTP Client

转自:http://www.cnblogs.com/dennieschang/p/6966403.html

 

在 Delphi XE 推出以前的年代,Delphi的展方向是笔直朝向库连结Windows 用程式个目不断前的,从Delphi 1开始,到Delphi 7,Delphi奠定了VB Killer的外号,主要依靠的就是与接功能超越其他开工具,而且超越的距离不只一个世代。 

在 .NET开始展,Delphi 8, Delphi .NET 不断延候,与库连接功能的方便性,仍然让许多ERP厂商、硬体厂商持续爱用 Delphi.

直到 Web 开与 App 开超越了 Windows 用程式的需求,VC, VB, Delphi 也开始随着波潮流,渐渐不再像 1990年代那么广受戴了。

在1990到 2010年之,Delphi的网路连线功能,主要是借由第三方元件来提供的,其中知名度最高,全球使用人数也最多的,应该就是 Indy 套元件了。

套元件在 2000 年前,叫做 WinShose,从第八版之后才改名Indy,全球投入套元件开的开,前后超40人,从最基的 TCP/IP 功能到各种定的Client与Server 端元件,笔者从中得益非常多,也开了当中的DNS Server元件,讯协定的深入了解,Indy团队是我不可或缺的师长

随着Delphi 工具走入了多平台开域,Indy的局限性也在两三年凸了出来,主要是在各个作上面于SSL与加密功能的支援无法合到作内建的功能所致。

由于个局限性,Delphi XE6开始,REST Client系列元件渐渐开始成 Delphi 团队的重点开发项目之一,所以我从 Delphi XE6, Delphi XE7 之后的版本,可以发现到,使用 TRESTClient, TRESTRequest, TRESTResponse 系列合的用程式越来越多了,原厂也不断鼓励大家使用套元件来提供 REST API 的连线功能。

REST API 的基是 HTTP 定,大多以 HTTP 的 POST 方法把 JSON 编码形式的参数传递到 Server,而 Server 再以 JSON 形式的参数回

作法也会稍有化,例如以 POST 方法把 Web-Form 编码形式的参数传递给 Server,Server 再以 JSON 形式把料回

形式不一而足,但相同的是 HTTP 定,最常用的也是以 POST 方法把参数传给 Server 端。

今天要跟大家分享的主是如何『使用 TRESTClient 与 TRESTRequest 作 HTTP Client』。

 

前面已提到,在没有 TRESTClient 整元件以前,我通常用的是 Indy 系列的元件来提供网路传输的功能,而在有了 TRESTClient 整元件,我在行平台上面就可以不需要另外配置函式,也能直接使用 https 与 server 连线了,在勒索病毒泛的今天,使用 https 会使用者比安心。

POST业说

在 HTTP 的 POST 作当中,参数跟 GET 作,Client端需要以 name=value&name2=value2 种形式行字串接,再送到 Server 端去。Get 跟 POST的差异,在于 Get 方法是把所有参数当做 URL 的一部分,送 HTTP GET 指令的候,参数同 URL  一起送。

而 POST 作业则送完 POST 指令后,把所有的参数与料随之送。依照 HTTP 型定的范,GET 作的 URL 是无法加密的,而且度也有限制。因此,当需要传递料比多,或者有机敏性,透 HTTPS 送,就是最直接,也最方便,更是目前最通用的料保方法。 

 POST 传递的参数,除了字串以外,常常包含了档案传递。我很常看到在网上面以按提供使用者选择要上的档案,也常看提供以拖拉的方式把档案上端系,尤其网页邮件系最常种作法。 

去以 TIdHTTP 元件的 POST 方法送参数,呼叫方式如下:

使用 TRESTClient 与 TRESTRequest 作为 HTTP Client(转)
 1 var
2 httpClient : TIdHTTP;
3 url, params, httpResultStr : string;
4 begin
5 url := 'http://mytestURL.com/test.php';
6 params := 'name=我的名字&test=测试';
7
8 httpClient := TIdHTTP.Create(self);
9 try
10 httpResultStr := httpClient.Post(url, params);
11 showMessage(httpResultStr);
12 finally
13 httpClient.Free;
14 end;
15 end;
使用 TRESTClient 与 TRESTRequest 作为 HTTP Client(转)

这样就可以把 params 字串的众参数到 server 去了。理上是这样,但事情并没有简单,在 HTTP 定当中要参数 Server,如果些字串包含了特殊字元,要先经过编码,而编码,是我一生都需要与之抗的繁复程序。

在 HTTP GET 方法当中,所有的参数除了要以 name=value 每一个参数做描述,以及需要用 & 来接各参数,所有的 value 都需要以 url encode 来脱 URL 保留字元的纠缠。name 是否需要编码呢?笔者建,name 就乖乖的用英文吧,可以省下很多问题,以及些可避免的问题所需要的时间

那么同的功能,以 TRESTClient 跟 TRESTRequest 要怎么达成呢? 也很容易,作法如下:

1. 在 form 里面放上 TRESTClient 跟 TRESTRequest 元件各一。

2. 把要传递的参数加到 TRESTRequest 体的 params 属性里面去,个属性的型是 TArray,所以可以存放多参数。

3. 定 TRESTClient 要送参数的URL,注意,URL 是定在TRESTClient 哦!

4. 定 TRESTRequest 要使用的传输方法,要POST(因正在介的是POST方法,按照您的需求整)

5. 呼叫 TRESTRequest 体的 execute 方法,就可以把料送去 server 了。

 

写成 Delphi 的程式,会像以下这样:

使用 TRESTClient 与 TRESTRequest 作为 HTTP Client(转)
self.RESTClient1.BaseURL :=
'http://我的网址/acceptNewCard.php';
self.RESTRequest1.Params.Clear;
self.RESTRequest1.Method := rmPOST; self.RESTRequest1.AddParameter('test', self.EditCardNo.Text);
self.RESTRequest1.AddParameter('name', self.EditName.Text);
使用 TRESTClient 与 TRESTRequest 作为 HTTP Client(转)

是不是很容易呢?的确很容易,里问题等下再深入探,先来看 server 端要怎么接收些个参数,我用 PHP 当范例,需要用 C#,JSP的者朋友们请自行转译喔⋯⋯

 

PHP Server 端接收 POST 参数的方法

从 1994 年开始,笔者就陆续撰文明 HTTP POST 方法如何接参数,包含了CGI 用C,perl等作,也包含 ISAPI 以 Delphi 作,近几年比流行的是 PHP,JSP,C#,但 PHP 程式码读起来比较简洁易懂,所以我就选择 PHP 来做范例了。 

在 PHP 里面,透GET 跟 POST 方法传递的参数,会被分存放在 $_GET 跟 $_POST 两个数里面,如果要偷懒,不想区分 GET 或 POST 方法,也可以从 $_REQUEST 取,当中有些安全性考量,最好勤一点,把它区分开来。

 

刚刚的例子来看,我们传了一个名 name,以及一个名 test 的字串,用的是 POST 方法,所以我得用以下两个数来存取两个字串:

•  $_POST['name']  数可以取得 Client 端送出来的 name 

•  $_POST['test']  数可以取得 Client 端送出来的 test

所以在 server 端,我可以这样写,来抓到两个料:

$name = $_POST["name"];

$test = $_POST["test"];

 

这样写会不会出问题呢? 答案是不会!如果使用者不入中文的

 

中文料的编码处

Delphi的开员绝大多数都是英美系的人,我推因此系的文字示与传输没有法完整的测试,但于我以中文的人来,从电脑诞生的那个年代,中文的示在每个操作、每种通讯协定的设计都比英文来的困

以上面的例子来看,如果我直接拿个例子来测试,笔者写的范例程式,传输资,Server 所抓到的文字并不是正确的中文字,如下所示:              

 使用 TRESTClient 与 TRESTRequest 作为 HTTP Client(转) 使用 TRESTClient 与 TRESTRequest 作为 HTTP Client(转)

可以看得出来,到 server 的候,server 是不到资讯的。是怎么回事呢?笔者属于不认输的好奇宝宝,使出了身解数,于解决了问题

 

 Web 程式的一定可以立刻推出来,这绝对是文字编码问题了,然而,是什么地方出问题?可能出问题的点我列出来跟大家分享:

•  HTTP Client 的 charset 

•  HTTP Request 里面的文字编码问题

检查的方向也是从两个关点出,第一点的检测很容易,从Object Inspector检查一下 RESTRequest1的定:

使用 TRESTClient 与 TRESTRequest 作为 HTTP Client(转)

AcceptCharset 确定是 UTF-8,没,所以定不是问题

接着,就要从 Client 端出去的料下手了。有者或『你怎么不怀疑Server端程式写了?』问题很好,之所以排除了问题,是因同一个 Server 端的 PHP 程式,我用了 Postman 做对测试,回果是正确的,因此判定是 Client 端程式的问题

接着笔者从 TRESTRequest.AddParameter 的各种多形式来尝试,AddParameter 个方法有以下几种多的形式:

procedure AddParameter(const AName, AValue: string); overload;
procedure AddParameter(const AName: string; AJsonObject: TJSONObject; AFreeJson: boolean = true); overload;
procedure AddParameter(const AName, AValue: string; const AKind: TRESTRequestParameterKind); overload;

三种形式我都测试过,从 AddParameter 的行中 trace 去看各个可能性,由于 TRESTRequest 的参数中,Get 跟 Post 的加入方法是混用的,在程式里面编码又会有点不同。

在 REST.Client.pas 里面,我曾经怀过编码错误,所以也在各个数都察,最后,找到了原因与解法,至于程,就不多了,花了我两天咧。

原因:编码错误

用HTTP传递中文的候,必用UTF-8编码,但一定要得,中文字在作中,都是UCS32编码象在Windows里面如此,在Android里面如此,在iOS跟Mac我不确定,但理方法是一的。 

直接以 AddParameter('name', '中文测试'); 把参数加 TRESTRequest 候,REST.Client.pas 的程式是把 '中文测试个字串直接抓 Ord 的料来做编码的,然而,个作法,是的!!!!!!!! 

在 HTTP 传递 UTF-8 料的候,我传递的是 UTF-8 文字的二料,但直接把 '中文测试个字串直接拿来成二位? 当时编码并不是 UTF-8 啊,当然怎么编码送到 server 都是的!!!!

解法:AddParameter之前先做 UTF-8 转换

个解法,笔者第一天就已想到,只是很想像以前改 Indy 程式一,直接改好 REST.Client.pas 之后,回馈给原厂使用,所以花了不少时间找方法,最后发现这个方法不用到 REST.Client.pas,又能正确理,就直接么跟大家分享了,写成 Delphi 程式如下:

使用 TRESTClient 与 TRESTRequest 作为 HTTP Client(转)
var
nameStr : String;
begin
...
nameStr := TIdURI.ParamsEncode(nameStr, IndyTextEncoding_UTF8);
self.RESTRequest1.AddParameter('name', nameStr,
TRESTRequestParameterKind.pkGETorPOST,
[TRESTRequestParameterOption.poDoNotEncode]);
...
end;
使用 TRESTClient 与 TRESTRequest 作为 HTTP Client(转)

在把字串透 AddParameter 加入参数列之前,我先把字串做个 UTF-8 转换,在里用的是 TIdURI 的类别方法 ParamsEncode,个方法只有两个参数,第一个参数是字串内容,第二个参数是要文字编码的种,在里我选择了 UTF8,写法就是上面范例程式的第一行。

接着,在呼叫 AddParameter 的候,我使用了多形式当中的第三种,要求 AddParameter 料的候不要再我的编码,因我已经处理好了。

这么修改过之后,在各个作业系统当中,执行结果都是正确的,上面两个图以 Windows 作业系统为例,现在我们拿 Android 截图来做为例子:

使用 TRESTClient 与 TRESTRequest 作为 HTTP Client(转) 使用 TRESTClient 与 TRESTRequest 作为 HTTP Client(转)

者可以看到右的截里面,server 回料已是正确的中文字了。

最后,我把 PHP 程式也附上来大家参考:

使用 TRESTClient 与 TRESTRequest 作为 HTTP Client(转)
 1 <?php
2 date_default_timezone_set("Asia/Taipei");
3 header('Content-Type: charset=utf-8');
4
5 include("public/DBClassPDO.php");
6 $objDBPDO = new DBClassPDO();
7
8 $cardNum = $_POST["cardNum"];
9 $floorIdx = $_POST["floorIdx"];
10 $name = $_POST["name"];
11 $houseNum = $_POST["houseNum"];
12
13 $params = array();
14 $params['name'] = $name;
15 $params['cardno'] = $cardNum;
16 $params['houseNum'] = $houseNum;
17 $params['floorIdx'] = $floorIdx;
18 $params['picFilename'] = $fileSaveName;
19 $params['created'] = 0;
20
21 $result["resultCode"] = "0";
22 $result["result"] = "成功";
23 $result["sqlcmd"] = $name;
24
25 $jsonStr = json_encode($result);
26 echo $jsonStr;
27 ?>
使用 TRESTClient 与 TRESTRequest 作为 HTTP Client(转)

是最基本的传递字串,下次再大家示范怎么档案,透 TRESTRequest来做也是很简单的,TRESTRequest 跟 TRESTClient 的确是取代 TIdHTTP 的好工具。

使用 TRESTClient 与 TRESTRequest 作为 HTTP Client(转)的更多相关文章

  1. 使用 TRESTClient 与 TRESTRequest 作为 HTTP Client

    在 Delphi XE 推出以前的年代,Delphi的发展方向是笔直朝向资料库连结Windows 应用程式这个目标不断前进的,从Delphi 1开始,到Delphi 7,Delphi奠定了VB Kil ...

  2. 使用 TRESTClient 與 TRESTRequest 作為 HTTP Client 之二 &lpar;POST 檔案&rpar;

    使用 HTML 进行文件上传,已经是很平常的应用了,在手机App里面,也常常会用到这个作业,例如拍照上传,或是从相簿选取照片上传,都是很常见的. 在 HTML 的 Form 里面,要让使用者选择文件上 ...

  3. Delphi APP 開發入門(十)REST Client 開發

    Delphi APP 開發入門(十)REST Client 開發 分享: Share on facebookShare on twitterShare on google_plusone_share ...

  4. 我的第一个REST客户端程序!

    Delphi:XE8 看了好几天的资料了,也没有弄出来一个REST程序,尝试了XE8中带的例子,也都没有搞懂.我在网上不断搜索,看是否能够找到适合自己的文章,希望能够做出来一个REST的小例子,万幸, ...

  5. delphi 各版本的特性

    delphi 各新版本特性收集 Delphi XE6新增了一些特性并增强了原有的功能,主要有以下几个方面:   IDE(整合开发环境)   Internet XML(扩展标记语言) Compiler( ...

  6. delphi c&plus;&plus;builder JSON 生成与解析 例子

    json,System.JSON,REST.JSON JSON有两种数据结构,对象和数组. 对象在js中表示为“{}”括起来的内容,数据结构为 {key:value,key:value,...} 数组 ...

  7. Delphi调用REST

    Delphi调用REST很简单,首先在界面上放上: RESTClient1: TRESTClient; RESTRequest1: TRESTRequest; RESTResponse1: TREST ...

  8. Delphi XE5中的新增内容

    Delphi XE5中的新增内容 Delphi XE5是所有Delphi开发人员的必须备升级,并且是来自Embarcadero的获奖的.多设备应用开发解决方案的最新版本.使用Delphi XE5的新特 ...

  9. vmware里面的名词 vSphere、vCenter Server、ESXI、vSphere Client

    vmware里面的名词 vSphere.vCenter Server.ESXI.vSphere Client vSphere.vCenter Server.ESXI.vSphere Client VS ...

随机推荐

  1. js中array的join和concat的区别

    首先:concat方法定义:concat() 方法用于连接两个或多个数组.该方法不会改变现有的数组,而仅仅会返回被连接数组的一个副本.举例说明:1 /*concat()结果返回的是一个数组*/ 2 3 ...

  2. quick cocos2d-x 入门---井字棋

    学习quick cocos2d-x 第二天 ,使用quick-x 做了一个井字棋游戏 . 我假设读者已经 http://wiki.quick-x.com/doku.php?id=zh_cn阅读了这个链 ...

  3. linux source与 &period; 命令

    source命令用法:source FileName作用:在当前bash环境下读取并执行FileName中的命令.注:该命令通常用命令“.”来替代.如:source .bash_rc 与 . .bas ...

  4. Laravel 安装predis 扩展

    在安装predis扩展之前先安装composer,安装教程在https://getcomposer.org/download/: php -r "copy('https://getcompo ...

  5. python 数据类型之数值型

    1.在python在数值的类型大概包括int float complex decimal 1.int 在3.x中它不在有最大值的限制. 2.float它更加连近于C语言中的double 3.compl ...

  6. 【剑指offer】第一个字符只出现一次

    转载请注明出处:http://blog.csdn.net/ns_code/article/details/27106997 题目描写叙述: 在一个字符串(1<=字符串长度<=10000,所 ...

  7. trove instance service 总结

    def create(self, req, body, tenant_id): # TODO(hub-cap): turn this into middleware LOG.info(_LI(&quo ...

  8. 公司用中会用到的iOS开源库和第三方组件&lpar;不断更新&period;&period;&period;&rpar;

    分享一些目前我个人接触到的一些第三方组件和开源的库, 感谢开源, 减少了我们的开发成本, 节约了我们大量的时间, 让我们有更多的时间和精力专注做我们自己的产品.总有没有接触过的 , 总有你会用到的 , ...

  9. 基于ExtJs6前台&comma;SpringMVC-Spring-Mybatis&comma;resteasy&comma;mysql无限极表设计,实现树状展示数据&lpar;treepanel&rpar;

    先从后台讲起 1.表的设计 parent_id就是另外一条记录的id,无限极表设计可以参考  http://m.blog.csdn.net/Rookie_Or_Veteran/article/deta ...

  10. 家居环境监測系统设计(PC上位机版)(手机APP版待定)

    下面是我的毕业设计:家居环境监測系统设计(PC上位机临时版.手机app版待定).本系统採用STC12C5A60S2单片机.结合传感器.分别对空气湿度.空气温度.气压.海拔.进水温度.出水温度.光照强度 ...