使用 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 在新版的程式碼給大家。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM