2020年10月27日 星期二

談 CodeChargeStudio 的 upload 問題

原始的CCS文件:Description

File Upload 元件,使用來上傳到指定的 Web server.
使用 (<input type="file">) 讓使用者在他自己的電腦上瀏覽選擇檔案。
用戶選擇、且按了送出鍵,就上傳。
File Upload 元件會檢查 檔案大小限制 file size limit。
同時檢查允許的檔案格式副檔名。
成功上傳到 server (註一)以後,CCS就會給他一個檔名"yyyymmddHHnnss#.<originalName>",
'yyyymmddHHnnss' 是當時系統日期時間。
#加上序號,確保名稱唯一性。
File Upload 必須在 Record form 或 Editable Grid。


CCS的 upload control 必須在 Record/Grid 裡面使用。

使用 html 的 <input type="file"> 來做上傳。

會在 HTML 產生這段碼:

<!-- BEGIN FileUpload name -->
  <input type="hidden" name="{ControlName}" value="{State}">
  <!-- BEGIN Info --> {FileName} {FileSize} bytes <!-- END Info -->
  <!-- BEGIN Upload --><input type="file" name="{FileControl}"><!-- END Upload -->
  <!-- BEGIN DeleteControl --> Delete <input type="checkbox" name="{DeleteControl}" {DeleteChecked}><!-- END DeleteControl -->
<!-- END FileUpload name -->

File Input Control

File Upload 元件裡面主要的元素是 file input control. HTML 碼如下:

<input type= "file" name= "{ControlName}">

這個是讓用戶可以在他的電腦上瀏覽選取檔案。

檔案選擇以後,送出鍵,就會上傳到 server。(這一段:註一,由PHP處理)
在儲存到主機之前,CCS會檢查檔案大小以及格式,如果有錯,就會產生錯誤訊息,檔案不會儲存。

Note that the file input control appears when a new record is being inserted or there is no existing file associated with the record being viewed. If the record being viewed has an existing file, the File Upload component will display information about the file and hide the file input control. 


* 研究CCS的程式碼以後(包含:主程式.php、common.php、classes.php、還有 CCS所附的sample2) 發現,配合 upload 一定要配合一個 uploaded files 的  資料庫  table,例如:files,然後在該 upload control的 property裡面綁定的 table name、field等綁定,才能夠真正正確的執行整個CCS所提供的功能。如果沒有綁定table、field等,好像就是上傳到 Temporary Folder,無法再搬移到 File Folder裡。因為搬移這個動作,是設計在 Record form裡面的 insert()之後動作的!

這一點,我試了好久,沒有綁定table、一直試 File Folder,就是無用!只有在 Temporary Folder而已!只好去K CCS的程式碼、找 Sample2裡面的程式,才發現這樣!

* 接下來,我要解決中文檔名的問題。因為上傳中文檔名,在 php的 move_uploaded_file()這裡會有錯誤。我們無法去改 php,只有自己想辦法解決!

move_uploaded_file(),只能接受 big5檔案名稱,所以,在使用以前,必須將utf8的中文名稱轉換成 big5,才可以呼叫 move_uploaded_file()

修改: classes.php

line 1839:
while($file_exists) {
// $ActualFileName = date("YmdHis") . $index . "." . $FileName;
$ActualFileName = date("YmdHis") . $index . "." . iconv("utf-8", "big5", $FileName);
$file_exists = file_exists($this->FileFolder . $ActualFileName) || file_exists($this->TemporaryFolder . $ActualFileName);
$index++;
}
if( move_uploaded_file($_FILES[$FileControl]["tmp_name"], $this->TemporaryFolder . $ActualFileName)) {
...
(略)
...
}

主要是 將 $FileName 用 iconv("utf-8","big5",$FileName)轉換成 big5

然後,交由 move_uploaded_file()處理就可以

CCS 將上傳的檔案(記住:中文檔名為 big5碼的)存放到 設定的 TemporaryFolder 裡面。

然後、綁定的TABLE新增一筆紀錄,此時要將檔名由 big5轉回 utf-8,才能正確儲存。

試了整個晚上,終於試出來了!就是在 upload 綁定的 record form 的Event: fileForm_ds_BeforeExecuteInsert 裡面,直接去修改 INSERT 的 SQL ,整個改掉,改成:

$fileForm->DataSource->SQL = 
"INSERT INTO files  (file_name, file_date_uploaded, file_owner_id, file_status) VALUES( " .
CCToSQL( iconv("big5","utf-8",$fileForm->FileUpload1->GetValue()), ccsText) . ",".
 " NOW() " . "," .
CCToSQL( $fileForm->file_owner_id->GetValue(), ccsInteger) . "," .
CCToSQL( $fileForm->file_status->GetValue(), ccsInteger) . ")"; 

主要要點是:將 file_name,使用 iconv("big5", "utf-8", filename欄位) 改回 utf-8

這樣就完成了。

總結:

未來:1. Classes.php 要注意使用這個修改一行的版本。本來想要盡量不要動到CCS預設的 Classes.php檔案,但是試了幾天,都找不到方法可以不動。那就只好動它了!記得維持這個版本。萬一,這版本被CCS改回去了。就記得手動去改 1840 那一行。

2. upload control 所在的 網頁檔,記得要綁定一個 Record / Editable Grid,才可以使用 upload 元件,同時,是先定義好files  table,裡面的欄位 filename 等。然後,在該 record 的 BeforeExecuteInsert Event 去改掉 INSERT SQL ,將 中文檔名編碼格式由 big5 改回 utf-8,如上。(去 copy來改比較快啦!)

完成!


註一:php 原始上傳是先上傳到 php.ini 裡面定義的 tmp folder,然後紀錄在$_FILE["file"] 系統變數裡面

分別是:

$_FILES["file"]["name"] - the name of the uploaded file
$_FILES["file"]["type"] - the type of the uploaded file
$_FILES["file"]["size"] - the size in bytes of the uploaded file
$_FILES["file"]["tmp_name"] - the name of the temporary copy of the file stored on the server
$_FILES["file"]["error"] - the error code resulting from the file upload

然後:再呼叫 move_uploaded_file($_FILES["file"]["tmp_name"],  $_FILES["file"]["name"]);

2. CCS 的 upload control 可以設定 兩個 property: Temporary Folder、 File Folder。


註二:2020/10/28 中午,將以上昨晚在local 電腦(windows系統)測試都成功的東東,上傳到 Linux Server!結果發現:又錯了!問題就在於 Windows 的中文檔名,與 Linux 的中文檔名,編譯的 碼 不一樣!

結果,我試著將 昨天以前在 windows 上測試好幾天成功的東東都拿掉,還原回原本CCS上的原始碼狀態,竟然成功運作!哈哈哈!也就是說我這幾天都做白工了!

唉!耶沒有做白工啦!至少對CCS的內部設計,更清楚一些了。也興起我運用他來設計一套 Generator 的想法!

哈哈!功不唐捐啦!~~~


沒有留言:

張貼留言

如何判斷現在FORM是在 insert mode? 還是 update mode?

只要用  if (empty({primary_key})) 就可以知道是否為新增模式了。 如果 {promary_key} 是空白的,那麼就是在新增模式;反之,就是更新模式。 以上。