使用 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 檔案)的更多相关文章

  1. 使用 TRESTClient 与 TRESTRequest 作为 HTTP Client

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

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

    使用 TRESTClient 与 TRESTRequest 作为 HTTP Client 转自:http://www.cnblogs.com/dennieschang/p/6966403.html   ...

  3. ZooKeeper源码阅读——client(二)

    原创技术文章,转载请注明:转自http://newliferen.github.io/ 如何连接ZooKeeper集群   要想了解ZooKeeper客户端实现原理,首先需要关注一下客户端的使用方式, ...

  4. Hadoop HBase概念学习系列之HBase里的Client(二十二)

    这个,很简单,但凡是略懂大数据的,就很清楚,不多说,直接上图.

  5. 一步一步实现视频播放器client(二)

    实现主体界面:                 222.png (64.46 KB, 下载次数: 0) 下载附件  保存到相冊 前天 21:02 上传 比較常见的一种布局.以下几个button.点击后 ...

  6. 7-MySQL-Ubuntu-操作数据表的基本操作(二)

    修改数据表的结构 (1)向数据表中添加新的字段 alter table 表名 add 字段名 类型及约束;  (2)修改字段的属性(字段的数据类型和约束) 注:modify不能修改字段名,只能修改字段 ...

  7. PAM 認 證 模 組

    作者:陳柏菁 E-mail 作用:限制哪些用户或者组可以从哪里登陆,或者可以建立/etc/nologin立即阻止一般用户登陆,限制 user可以使用的资源.例如cpu,文件,登陆数量,某些服务的登陆时 ...

  8. Cen0S下挂载设备

    在CentOS中,如果我们要查看光驱,U盘或者要把安装包挂载到某个文件夹,我写下我的一些理解. 所谓的挂载,就是把物理设备或者文件(包含安装文件,压缩包等等),与系统中的某个目录建立一个快捷方式,然后 ...

  9. X86 Booting Sequence

    1.BIOS 0xFFFF0 電源正常啟動後,x86 CPU 會先執行 0xFFFF0,也就是 BIOS ROM 的進入點.由於 0xFFFF0 ~ 0xFFFFF 只有少的很可憐的 16 bytes ...

随机推荐

  1. vue请求网络图片403错误,图片有占位但是显示不出来解决办法

    在index.html 增加一个meta标签 <meta name="referrer" content="no-referrer" />

  2. Java软件工程的弹幕调试原则

    日期:2019.4.25 博客期:054 星期四 今天是把很久之前的那个相关程序——一维数组的最大和的子数组的求取信息,我们今天的任务就是把每一步的信息都要进行输出查看! 如下图: package p ...

  3. centos搭建git服务

    一.服务器yum -y install git git init --bare test.gitcd test.gitpwd //打印当前目录,假设是:/home/root/git/test.gitg ...

  4. PADS Layout VX.2.3 制作PCB封装(Decal)时,导入DXF文件

    操作系统:Windows 10 x64 工具1:PADS Layout VX.2.3 进入PCB封装编辑器(Decal Editor),点击Drafting Toolbar > Import D ...

  5. MVC和MVP设计模式

    参考博客http://www.cnblogs.com/end/archive/2011/06/02/2068512.html ####MVC模式M:model 模型V:view 视图C:control ...

  6. Java读取证书

    import java.io.FileInputStream; import java.security.Key; import java.security.KeyFactory; import ja ...

  7. Kubernetes 1.10.0离线安装

    讲述如何通过离线的方式安装Kubernetes,主要用于对Kubernetes的研究学习,不建议在生产环境使用,安装包获取地址: 链接:https://pan.baidu.com/s/1nX5_mem ...

  8. VIM系统复制粘贴

    1 需求 系统复制粘贴主要是满足下面两个需求. 在多个对象之间复制粘贴 vim窗口与vim窗口之间 外部界面与vim窗口之间 不变复制粘贴.从外部界面复制粘贴到vim窗口时,文本不发生任何变化. 2 ...

  9. Chrome 无法自动填充密码

    问题: chrome 同步一切正常,在密码管理器https://passwords.google.com 也能看到自己保存的密码 但是在 设置 - 密码中看不到保存的密码,只能看到 “一律不保存” 的 ...

  10. 【数据结构】KMP算法

    我还是不太懂... 转2篇大神的解释    1>https://www.cnblogs.com/yjiyjige/p/3263858.html     2>https://blog.csd ...