使用 TRESTClient 與 TRESTRequest 作為 HTTP Client 之二 (POST 檔案)
使用 HTML 进行文件上传,已经是很平常的应用了,在手机App里面,也常常会用到这个作业,例如拍照上传,或是从相簿选取照片上传,都是很常见的。
在 HTML 的 Form 里面,要让使用者选择文件上传,通常会这样写:
<input type=”file” name=”fileId1” id=”fileId1”/>
当我们在 HTML 里面这么写,网页浏览器会自动在画面上显示一个按钮,点选之后,会出现文件选择的对话框让使用者选择文件。
但是,在手机作业系统中,为了提供文件系统的Sandbox 功能,并无法从网页直接提供相簿照片选择或拍照上传的功能,所以大多数类似的功能,还是得透过 App 提供才行。
在这个范例中,为了让使用者能直觉使用文件选择的功能,所以也同时介绍了如何从手机相簿选择与拍照上传的功能。
如何让Delphi程式提供相簿选照片的功能
在Delphi环境中,要提供使用者从相簿选相片,或是启动相机拍照,都要透过 TAction 来完成,只是从相簿选照片跟启动拍照功能,是以两个不同的 TAction 来完成的。虽说是不同的 TAction 处理不同的程序,但取得照片的时候,回传给程式的结果都是用TBitMap 来储存相片。
换句话说,取得了 TBitMap 之后,我们想要对TBitMap做任何影像处理、格式处理,都可以由我们的程式码来操作。
从 Delphi XE6 之后,这些直接使用行动装置功能的程式码,都已经被载入到TAction里面了,我们只需要在使用上了解如何把TAction跟按钮事件绑在一起即可。
首先,我们需要在 Form 上面放上一个 TActionList 元件,然后双击这个元件,就可以显示出 ActionList 的编辑画面:

在这画面中,我们要新增Media Library 的两个 Standard Action,就是上图的TakePhotoFromLibraryAction (从相簿取得照片),以及TakePhotoFromCameraAction (从相机拍摄照片)。

建立两个 Action 之后,我们就需要为这两个 Action 设定 onDidFinish 跟 onDidCancel 的事件,前者是用来处理确定拍摄/挑选照片的事件,后者则是用来处理取消拍摄/挑选照片的事件。
在这个范例中,onDidFinish 的时候,会把回传来的图片资料直接放在画面上的 TImage 元件显示,所以它的程式码很单纯:
Procedure TForm2.TakePhotoFromCameraAction1DidFinishTaking(Image: TBitmap);
Begin
Self.Image1.Bitmap.Assign(Image);
End;
Procedure TForm2.TakePhotoFromLibraryAction1DidFinishTaking(Image: TBitmap);
Begin
Self.Image1.Bitmap.Assign(Image);
End;
就是直接把 Image Assign 给 Image1.Bitmap 属性即可。
最后,点选按钮上传,完整的程式码如下:
Procedure TForm2.btnUploadClick(Sender: TObject);
Var
newItem: TRESTRequestParameter;
allPass: Boolean;
imgPath, houseNum, floorIdx: string;
nameStr: String;
obj: TJSONObject;
begin
allPass := True;
if self.EditName.Text = ‘’ then begin
allPass := False;
ShowMessage(‘请填写住户名字’);
End
Else if (Length(self.EditCardNo.Text) < 5) or
(Length(self.EditCardNo1.Text) < 5) then begin
allPass := False;
ShowMessage(‘请填写悠游卡卡号10码’);
End
Else if self.Image1.Bitmap.IsEmpty then begin
allPass := False;
ShowMessage(‘请提供悠游卡感应卡号照片’);
End;
If allPass then begin
Self.RectWaiting.Visible := True;
Self.AniIndicator1.Enabled := True;
imgPath := System.IOUtils.TPath.Combine
(System.IOUtils.TPath.GetDocumentsPath, ‘tmp123.png’);
Self.Image1.Bitmap.SaveToFile(imgPath);
Self.RESTClient1.BaseURL :=
‘http://testURL/acceptNewCard.php’;
Self.RESTRequest1.Params.Clear;
RESTRequest1.Method := rmPOST;
nameStr := self.EditName.Text;
self.RESTRequest1.AddParameter(‘cardNum’, self.EditCardNo.Text + ‘:’ +
self.EditCardNo1.Text);
nameStr := TIdURI.ParamsEncode(nameStr, IndyTextEncoding_UTF8);
self.RESTRequest1.AddParameter(‘name’, nameStr,
TRESTRequestParameterKind.pkGETorPOST,
[TRESTRequestParameterOption.poDoNotEncode]);
// self.RESTRequest1.AddParameter(‘name’, nameStr, TRESTRequestParameterKind.pkGETorPOST, [TRESTRequestParameterOption.poDoNotEncode]);
Case self.ComboBoxHouseNum.ItemIndex of
0: begin
houseNum := ‘1’;
end;
1: begin
houseNum := ‘374’;
end;
end;
houseNum := TIdURI.ParamsEncode(houseNum, IndyTextEncoding_UTF8);
self.RESTRequest1.AddParameter(‘houseNum’, houseNum);
floorIdx := IntToStr(self.ComboBoxFloor.ItemIndex + 1);
self.RESTRequest1.AddParameter(‘floorIdx’, floorIdx);
self.RESTRequest1.AddFile(‘picFilename’, imgPath);
self.RESTRequest1.Execute;
obj := TJSONObject.ParseJSONValue(self.RESTRequest1.Response.JSONText)
as TJSONObject;
ShowMessage(obj.GetValue<String>(‘result’));
Self.RectWaiting.Visible := False;
Self.AniIndicator1.Enabled := False;
End;
End;
上面的程式码里面,处理文件的重点只有一行:
Self.RESTRequest1.AddFile(‘picFilename’, imgPath);
在更前面一点的程式码中,imgPath 是由TImage.Bitmap即时存下来的照片,这个范例只适用于 Delphi 10.2 (Tokyo) 以后的版本,因为在 Berlin 当中,对于文件的 MIME Type 还没有完全支援,所以在 Berlin 或 Seattle 当中要使用这个方法上传文件的朋友,请升级吧,我也没办法直接提供 TRESTClient 在新版的程式码给大家。
使用 TRESTClient 與 TRESTRequest 作為 HTTP Client 之二 (POST 檔案)的更多相关文章
- 使用 TRESTClient 与 TRESTRequest 作为 HTTP Client
在 Delphi XE 推出以前的年代,Delphi的发展方向是笔直朝向资料库连结Windows 应用程式这个目标不断前进的,从Delphi 1开始,到Delphi 7,Delphi奠定了VB Kil ...
- 使用 TRESTClient 与 TRESTRequest 作为 HTTP Client(转)
使用 TRESTClient 与 TRESTRequest 作为 HTTP Client 转自:http://www.cnblogs.com/dennieschang/p/6966403.html ...
- ZooKeeper源码阅读——client(二)
原创技术文章,转载请注明:转自http://newliferen.github.io/ 如何连接ZooKeeper集群 要想了解ZooKeeper客户端实现原理,首先需要关注一下客户端的使用方式, ...
- Hadoop HBase概念学习系列之HBase里的Client(二十二)
这个,很简单,但凡是略懂大数据的,就很清楚,不多说,直接上图.
- 一步一步实现视频播放器client(二)
实现主体界面: 222.png (64.46 KB, 下载次数: 0) 下载附件 保存到相冊 前天 21:02 上传 比較常见的一种布局.以下几个button.点击后 ...
- 7-MySQL-Ubuntu-操作数据表的基本操作(二)
修改数据表的结构 (1)向数据表中添加新的字段 alter table 表名 add 字段名 类型及约束; (2)修改字段的属性(字段的数据类型和约束) 注:modify不能修改字段名,只能修改字段 ...
- PAM 認 證 模 組
作者:陳柏菁 E-mail 作用:限制哪些用户或者组可以从哪里登陆,或者可以建立/etc/nologin立即阻止一般用户登陆,限制 user可以使用的资源.例如cpu,文件,登陆数量,某些服务的登陆时 ...
- Cen0S下挂载设备
在CentOS中,如果我们要查看光驱,U盘或者要把安装包挂载到某个文件夹,我写下我的一些理解. 所谓的挂载,就是把物理设备或者文件(包含安装文件,压缩包等等),与系统中的某个目录建立一个快捷方式,然后 ...
- X86 Booting Sequence
1.BIOS 0xFFFF0 電源正常啟動後,x86 CPU 會先執行 0xFFFF0,也就是 BIOS ROM 的進入點.由於 0xFFFF0 ~ 0xFFFFF 只有少的很可憐的 16 bytes ...
随机推荐
- [吐槽]webpack4
https://webpack.js.org/guides/tree-shaking/ https://www.webpackjs.com/guides/ 插件都过时被替代了,中文文档也没更新过来,坑 ...
- 洛谷P5284 [十二省联考2019]字符串问题 [后缀树]
传送门 思路 设\(dp_i\)表示以\(i\)结尾的\(A\)串,能达到的最长长度. 然后发现这显然可以\(i\)往自己控制的\(k\)连边,\(k\)往能匹配的\(j\)连边,就是个最长路,只要建 ...
- java 冒泡排序 day003
一.冒泡排序: 利用冒泡排序对数组进行排序 二.基本概念: 依次比较相邻的两个数,将小数放在前面,大数放在后面.即在第一趟:首先比较第1个和第2个数,将小数放前,大数放后.然后比较第2个数和第3个数, ...
- luoguP2502旅行
2006河南省选 思路:(参考题解) 枚举最大的边(第\(i\)条),从这条边开始由大到小枚举.添边,当\(s\)和\(t\)联通时,此时即为以第\(i\)条边为最大边的答案,比较每个答案,判断输出. ...
- mysql 与 oracle 的连表update
mysql: update 表A a,表B b set a.xx=b.xx where a.id=b.id; oracle update 表A set a.xx=(select b.xx from 表 ...
- python3下的twistedPOST请求网页
在python2中我们使用twisted比较方便,网上资料也比较多,但是通常在python3中使用的时候,并不能成功.我也是找了好多资料没有成功之后,自己去尝试做小白鼠,测试了很久之后,发现传递给tw ...
- Keep-Alive 是什么?
Keep-Alive 是什么? 概观 默认情况下,HTTP链接通常在请求完成之后关闭.这意味着服务端在完成响应的交付之后便关闭了TCP链接.为了让链接保持打开,来满足多请求,可以使用keep-aliv ...
- IBOS云办公系统二次开发之功能介绍(PHP技术)
IBOS自动化办公系统是我见到的功能.架构最好的开源自动化办公系统,功能与企业需求吻合度之高.架构之灵活,让我不得不将之介绍给大家,让跟多需要学习PHP开发的朋友来了解她,拥抱她! 如果您还没有很好的 ...
- Anaconda的安装与使用
1. 安装Anaconda(Command Line) 1.1 下载 首先去Anaconda官网查看下载链接,然后通过命令行下载: $ wget https://repo.anaconda.com/a ...
- react native 中实现个别页面禁止截屏
这里主要用到了原生模块,下面贴出FlagSecureModule.java的代码 package com.studyproj.flagsecure; import android.util.Log; ...