使用 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 方法送参数,呼叫方式如下:

 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;

这样就可以把 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 的程式,会像以下这样:

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);

是不是很容易呢?的确很容易,里问题等下再深入探,先来看 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 所抓到的文字并不是正确的中文字,如下所示:              

  

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

 

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

•  HTTP Client 的 charset 

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

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

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 程式如下:

var
nameStr : String;
begin
...
nameStr := TIdURI.ParamsEncode(nameStr, IndyTextEncoding_UTF8);
self.RESTRequest1.AddParameter('name', nameStr,
TRESTRequestParameterKind.pkGETorPOST,
[TRESTRequestParameterOption.poDoNotEncode]);
...
end;

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

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

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

 

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

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

 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 ?>

是最基本的传递字串,下次再大家示范怎么档案,透 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 之二 (POST 檔案)

    使用 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++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. 3dsmax不同版本 pyside qt UI 设置max窗口为父窗口的方法

    3dsmax不同版本 pyside qt widget 设置 max 窗口为父窗口的方法 前言: 3dsmax 在 2014 extension 之后开始集成 Python 和 PySide,但是在版 ...

  2. Java集合及LIst接口

    一.集合的概念 1.概述: 在学习集合前,先回忆一下数组的一个特征---数组有固定的长度,定义一个数组: int[] array = new int[]; 而针对数据长度可变的情况,产生了集合, ja ...

  3. P2279 [HNOI2003]消防局的设立

    P2279 [HNOI2003]消防局的设立考场上想出了贪心策略,但是处理细节时有点问题,gg了.从(当前深度最大的节点)叶子节点往上跳k个,在这里设消防局,并从消防局遍历k个距离,标记上. #inc ...

  4. 简单总结下opacity、transparent以及rgba

    这几个概念最开始学的时候只是有个大致印象,现在复习这部分的知识点,发现不仔细区分一下,还真有点混乱. 三者共同点是都和透明有关.先分着来说一下: 1.opacity用来设置元素的不透明级别,从 0.0 ...

  5. Your ApplicationContext is unlikely to start due to a @ComponentScan of the default

    问题:** WARNING ** : Your ApplicationContext is unlikely to start due to a @ComponentScan of the defau ...

  6. BZOJ.3784.树上的路径(点分治 贪心 堆)

    BZOJ \(Description\) 给定一棵\(n\)个点的带权树,求树上\(\frac{n\times(n-1)}{2}\)条路径中,长度最大的\(m\)条路径的长度. \(n\leq5000 ...

  7. 01背包-dp

    一 问题分析 二 代码实现 package Dp_0_1_bag; import java.io.BufferedWriter; import java.io.FileWriter; import j ...

  8. 安装完最小化 RHEL/CentOS 7 后需要做的 30 件事情7. 安装 PHP PHP 是用于 web 基础服务的服务器端脚本语言。它也经常被用作通用编程语言。在最小化安装的 CentOS 中安

    CentOS 是一个工业标准的 Linux 发行版,是红帽企业版 Linux 的衍生版本.你安装完后马上就可以使用,但是为了更好地使用你的系统,你需要进行一些升级.安装新的软件包.配置特定服务和应用程 ...

  9. 超详细Gitlab Runner环境配置中文教程

    配置GitlabRunner环境 GitLab Runner 是一个开源项目, 它用来运行你定制的任务(jobs)并把结果返回给 GitLab. GitLab Runner 配合GitLab CI(G ...

  10. [BZOJ2863]愤怒的元首

    Description: Pty生活在一个奇葩的国家,这个国家有n个城市,编号为1~n. ​ 每个城市到达其他城市的路径都是有向的. ​ 不存在两个城市可以互相到达. 这个国家的元首现在很愤怒,他大喊 ...