Web Application 開 發 利 器 - WebSnap(九)

类别:Delphi 点击:0 评论:0 推荐:

Web Application 開 發 利 器 - WebSnap!

第 玖 章 、 圖 形 及 超 連 結

   

9-1 簡 單 的 圖 形 顯 示

 

  在 之 前 的 資 料 庫 程 式 中 我 們 並 未 討 論 到 如 何 處 理 Blob 欄 位 資 料 , 這 是 因 為 我 認 為 這 件 事 很 簡 單 , WebSnap 幫 你 做 掉 了 絕 大 部 份 的 工 作 , 你 只 要 照 著 資 料 庫 那 一 章 的 動 作 來 作 , 將 資 料 庫 換 成 有 Blob 欄 位 的 biolife.db 後 , 你 馬 上 就 可 以 看 到 圖 形 及 編 修 她 們 了 。 不 過 在 某 些 情 況 下 , 你 可 能 會 因 為 效 率 或 是 空 間 的 考 量 , 將 圖 形 改 為 只 存 檔 名 。 這 時 我 們 可 以 應 用 TAdapterImageField 來 處 理 這 類 的 需 求 , 在 我 們 撰 寫 這 個 資 料 庫 網 頁 之 前 , 我 們 得 先 弄 懂 TAdapterImageField 怎 麼 用 才 行 , 我 們 先 用 我 們 的 計 算 機 網 頁 來 做 試 驗 品 好 了 , 請 在 Calc Page Module 中 的 Adapter1.Data 特 性 中 新 增 一 個 TAdapterImageField , 並 設 定 她 的 HREF 特 性 值 :

 

( 必 須 要 設 定 WebAppDebuger 的 Path , 請 參 考 本 節 最 後 的 說 明 )

 開 啟 Visual Page Designer 新 增 一 個 AdapterDisplayField 到 AdapterFieldGroup1 中 , 你 會 看 到 如 下 的 Preview 畫 面 :

 

 

圖 形 是 空 的 , 這 是 因 為 我 們 是 在 設 計 模 式 中 , 而 我 們 設 定 的 HREF 是 URL 所 致 。 別 理 她 , 執 行 程 式 後 你 就 可 以 看 到 圖 形 顯 示 在 網 頁 上 了 , 除 了 明 白 設 定 HREF 之 外 , 我 們 也 可 以 選 擇 撰 寫 OnGetHREF 來 動 態 傳 回  HREF , 亦 或 是 撰 寫 OnGetImage 利 用 TFileStream 來 讀 取 Image File 後 回 傳 給 ImageField 顯 示 。 當 有 編 修 圖 形 的 需 求 時 , 我 們 可 以 撰 寫 OnUploadFile 事 件 來 將 使 用 者 上 傳 的 圖 型 存 檔 , 談 到 這 裡 你 應 該 想 出 了 如 何 解 決 只 存 檔 名 的 資 料 庫 圖 形 問 題 了 吧 。 只 是 問 題 可 能 沒 像 你 想 的 那 麼 容 易 , 因 為 我 們 只 存 文 字 檔 名 , 所 以 不 能 夠 使 用 TDataSetImageField , 也 就 沒 有 OnGetImage 這 個 事 件 可 以 使 用 , 除 非 我 們 自 己 處 理 Client 送 來 的 Request 訊 息 , 這 太 麻 煩 了 , 那 我 們 該 如 何 做 呢 ? 嗯 ! 好 問 題 , 我 們 下 一 節 就 處 理 這 個 問 題 。

  

9-2 圖 形 顯 示 的 進 階 處 理

 

 要 解 決 上 述 的 那 個 問 題 , 我 們 可 以 在 TDataSetAdapter 加 入 一 個 TAdapterImageField , 接 著 將 她 串 回 DataSetAdapter Fields 中 , 聽 起 來 很 簡 單 , 好 像 也 很 合 理 。 呵 ! 事 情 還 沒 完 呢 , 這 是 我 們 自 己 加 入 的 TAdapterImageField , 除 了 是 位 於 TDataSetAdapter 內 之 外 , 她 跟 TDataSetAdapter 可 毫 無 關 係 , 這 也 就 是 說 不 管 TDataSetAdapter 如 何 移 動 記 錄 指 標 , 我 們 的 TAdapterImageField 可 是 不 動 如 山 的 。 為 了 解 決 這 個 問 題 , 我 們 得 運 用 一 下 OnGetParam 特 性 , 迫 使 WebSnap 移 動 她 , TDataSetAdapter 及 TAdpterImageField 處 理 的 程 式 碼 如 下 :

 

function TImageDB.GetAppPath:string;

var

  FN: array[0..255] of char;

begin

  GetModuleFileName(hInstance,FN,SizeOf(FN));

  Result:=ExtractFileDir(FN);

end;

 

procedure TImageDB.AdaptPictureNameGetImage(Sender: TObject;

              Params: TStrings; var MimeType: String; var Image: TStream;

               var Owned: Boolean);

var

  AppPath:string;

  sImagePos:string;

begin

  AppPath:=GetAppPath;

  sImagePos:=Params.Values['PICTURE_NAME'];

  Image:=TFileStream.Create(AppPath+'\Images\'+sImagePos,fmOpenRead);

end;

 

procedure TImageDB.AdaptPictureNameUploadFile(Sender: TObject;

             AFile: TAbstractWebRequestFile);

var

  fs:TFileStream;

  AppPath:string;

  FileExt:string;

begin

  if AFile.ContentType = 'image/jpg' then

     FileExt:='.jpg'

  else if AFile.ContentType = 'image/pjpeg' then

     FileExt:='.jpg'

  else if AFile.ContentType = 'image/bmp' then

     FileExt:='.bmp'

  else if AFile.ContentType = 'image/gif' then

     FileExt:='.gif'

  else FileExt:='';

  if FileExt <> '' then

    begin

      fs:=TFileStream.Create(AppPath+'\Images\'+AdaptName.ActionValue.Values[0]+FileExt,fmCreate);

      fs.CopyFrom(AFile.Stream,0);

      DataSetAdapter1.DataSet.FieldByName('PICTURE').AsString:=AdaptName.ActionValue.Values[0]+FileExt;

      fs.Free;

    end;

end;

 

procedure TImageDB.AdaptPictureNameGetParams(Sender: TObject;

            Params: TStrings);

begin

  Params.Add('PICTURE_NAME='+AdaptPicture.Value);

end;

procedure TImageDB.AdaptPictureNameValidateFile(Sender: TObject;

            AFile: TAbstractWebRequestFile);

begin

  if (AFile.ContentType <> 'image/jpg') and

     (AFile.ContentType <> 'image/pjpeg') and

     (AFile.ContentType <> 'image/bmp') and

     (AFile.ContentType <> 'image/gif')  then

     raise EAdapterException.Create(' 未 知 的 圖 形 格 式 ');

end;

 

我 們 先 看 到 OnGetImage 事 件 , 我 們 在 這 裡 面 讀 取 圖 型 後 傳 回 給 Client 端 , 檔 名 是 從 Params 參 數 中 取 出 來 的 , 那 這 個 參 數 在 那 放 進 去 的 呢 ? 你 看 到 OnGetParams 部 份 了 嗎 ? 我 們 就 是 在 這 裡 將 參 數 放 進 去 的 , 看 下 列 的 HTML:

 

/Exam_1_TestSvr.MySimpleWeb/?PICTURE_NAME=TEST4.bmp&__id=ImageDB.DataSetAdapter1.PictureName" alt="">

 

我 們 利 用 了 這 個 參 數 迫 使 WebSnap 認 定 AdapterImageField 必 須 要 跟 著 DataSetAdapter 移 動 , 你 可 以 將 這 個 動 作 取 消 , 改 成 直 接 由 AdapterPicture 中 取 值 , 你 就 會 了 解 我 所 要 表 達 的 意 思 。 在 這 段 程 式 中 我 們 還 利 用 了 ValidateFile 事 件 來 判 別 檔 案 格 式 , 如 果 檔 案 格 式 不 符 的 話 , 我 們 就 引 發 一 個 例 外 , 這 個 例 外 的 訊 息 會 被 封 裝 到 Adapter.Errors 中 , 之 後 我 們 就 可 以 在 網 頁 中 顯 示 錯 誤 訊 息 , 這 個 程 式 中 我 利 用 了 一 個 新 的 Adapter 及 一 個 AdapterField , 並 在 HTML 中 加 入 以 下 的 Script 程 式 碼 :

 

<h3><%= Adapter1.ErrorMsg.Value %></h3>

 

以 及 下 面 的 取 值 程 式 碼 :

 

procedure TEditImageDB.AdaptErrorGetValue(Sender: TObject;

    var Value: Variant);

begin

  if ImageDB.DataSetAdapter1.Errors.ErrorCount > 0 then

     Value:=' 錯 誤 :'+ImageDB.DataSetAdapter1.Errors.Errors[0].ErrorText;

end;

 

詳 細 的 程 式 碼 你 可 以 在 範 例 程 式 中 的 ImageDB 、 EditImageDB 中 找 到 。 為 了 讓 WebAppDebuger 順 利 找 到 我 們 放 在 /Images 下 的 圖 型 , 我 們 必 須 將 這 個 路 徑 加 到 WebAppDebuger 中 , 請 開 啟 WebAppDebuger 的 Server|Options 選 單 並 加 入 你 的 路 徑 :

 

 

 本 章 後 記

 

  雖 然 我 在 本 文 中 都 使 用 BDE 來 處 理 資 料 庫 , 但 在 實 際 應 用 上 我 建 議 你 使 用 其 它 的 Driver , 因 為 BDE 有 Session 及 一 些 限 制 , 除 非 你 使 用 DataSnap , 否 則 開 發 出 來 的 網 站 可 能 無 法 承 受 太 多 用 戶 , 我 比 較 建 議 你 使 用 ADO 或 是 dbExpress 來 取 代 BDE , 或 者 直 接 使 用 DataSnap , 有 關 的 資 訊 你 應 該 可 以 在 其 它 書 中 找 到 , 我 就 不 再 多 說 了 , 在 OnGetImage 事 件 中 我 們 讀 取 了 圖 形 後 傳 回 Client 端 , 這 是 我 為 了 讓 你 了 解 OnGetImgae 事 件 的 用 法 特 別 寫 的 , 事 實 上 在 實 務 應 用 上 , 你 應 該 利 用 另 外 一 個 OnGetHREF 來 傳 回 圖 形 的 URL , 這 可 以 減 少 Web Server 的 負 擔 , 尤 其 是 程 式 與 圖 形 分 開 存 在 兩 個 Server 上 時 特 別 明 顯 , 這 可 以 讓 你 的 程 式 反 應 速 度 變 的 更 快 。 如 果 你 有 試 過 Delphi6 所 附 的 ImageProducer 的 話 , 你 應 該 知 道 Action 也 可 以 用 圖 形 來 做 連 結 , 我 會 在 下 面 討 論 她 .

 

<第 十 章 、 WebService+WebSnap>

本文地址:http://com.8s8s.com/it/it5764.htm