發表文章

目前顯示的是有「ColdFusion」標籤的文章

java.lang.NoSuchMethodError : org.apache.poi.poifs.filesystem.POIFSFileSystem.hasPOIFSHeader(Ljava/io/InputStream;)Z 問題解決方法

圖片
這個是在使用 POI 讀取 EXCEL 的 xlsx 檔案造成的 LOCAL.WorkBook = WorkBookFactory.create(FileStream); 使用 WorkBookFactory.create 時內部會呼叫 POIFSFileSystem.hasPOIFSHeader 函式。  如果呼叫失敗就出現這個錯誤訊息。 所以正常來說 POIFSFileSystem.class 裡面是包含 hasPOIFSHeader 函式的。 看大部分網路上的論壇討論結果或是意見,通常是 POI 所需使用的 jar 檔案使用了不匹配/不同版本的套件導致。 但這個問發現在我另一個 jetty 版的 Railo 4.0.4.001 伺服器上卻不會發生。 為什麼?兩個伺服器版本都是一樣的啊?裡面套件也應該相同的啊? 為此,我便進行研究了一下。 1、 發生這個錯誤 的伺服器是以 Tomcat7 執行的伺服器,而另一個 不會發生 這個錯誤的是以 jetty 執行的伺服器。而兩方的版本都是當初官方公佈的 4.0.4.001 版本。 2、比對兩邊使用 POI 的 jar 檔案,雙方的檔案尺寸是相同的,檔案數量也相同。     在此處 POI 相關的 jar 共有4個,這些都是同時隨伺服器版本一起發佈的,不是我另外安裝的,應該不會存在版本問題吧。 3、如果 POIFSFileSystem.class 不包含 hasPOIFSHeader 函式,理論上 jetty 伺服器也會出現錯誤。結果卻沒有發生這個錯誤,代表 POIFSFileSystem.class 是正確的。 但,為甚麼? 所以我用解壓縮軟體來觀察 jar 檔案的成員。 發現了奇怪的的是在 apache-poi.jar 和 apache-poi-tm-extractors.jar 裡面都出現了成員 POIFSFileSystem.class ,而且檔案尺寸完全不一樣! 而且路徑都在 org.apache.poi.poifs.filesystem 下,我猜這就是貓膩了。 因為在這種情況下只會有一個成員會被載入成功,至於是哪一個先被載入要看伺服器核心的 javaloader 處理規則。 因此,我把這兩個 jar 檔案分別解

coldfusion component (CFC) 另一種用法

圖片
一般 CFC 的寫法大概會像上面這樣: 而呼叫方式如下: <cfinvoke component= " COM.extfunc " method= " myescape " returnvariable= " escstr " >     <cfinvokeargument name= " sdata " value= "# myForm.note #" > </cfinvoke> <!--- 返回 escstr ---> <cfoutput> #escstr# </cfoutput> 上面這種方式屬於純 TAG 寫法,寫起來超麻煩,尤其參數很多時就會寫出一堆  <cfinvokeargument>,真是快昏倒了。 其實,也可以使用創建物件方式來使用這個 Component,會方便許多。 我們把上面的 cfc 改成下面方式 <cfcomponent displayname= " extfunc " hint= " 擴充功能 " >       <cffunction name= " Init " access= " public " returntype= " QueryUtility " output= " false "            hint= " Returns an initialized QueryUtility instance. " >           <!--- Return This reference. --->            <cfreturn THIS />       </cffunction>       <cffunction name= "myescape" access= "public" returntype=

Coldfusion 隱蔽式下載

圖片
一般下載時,通常會使用 <a href="URL" /> 這種方式使用者下載,而 URL 大多的做法是指明檔案所在的位置例如  <a href="http://MySite.com/download/picture/myPicture.png">。 這種方式有幾個問題: 1、如果使用者取得此聯結位址後,可以單獨由此取得檔案或盜連,故被直接拿到的風險會很高,因為這個 URL 就是一個開放的位址。 2、由於直接指定檔案位置,很多時候檔案就會被瀏覽器直接開啟,而非下載存檔,對於大部分使用者來說,這是一個貼心的模式,但是對於很多需要下載的商業用途場合就很麻煩,使用者還必須在聯結上按『右鍵』選擇『另存檔案』的方式,操作相當不便。 3、無法設定檢查使用者取得檔案的條件。 因此,透過隱蔽式下載就是一種很好的方法。 程式碼: < cfsetting enablecfoutputonly = "yes" > <!--- 避免下載檔案遇到中文檔名無法正常下載問題而使用的功能,也可以避免使用者知道實際檔案儲存位置 ---> <!--- Arguments : file = 指定檔案名稱 ---> < cftry > <!--- 判斷使用者來源聯結是否來自本伺服器 或是直接下載,當直接下載時 REFERER 會是 空值--->     < cfif findnocase (CGI.SERVER_NAME,CGI.HTTP_REFERER) LTE 0 >     < cfthrow type = "RefererError" message = "#CGI.HTTP_REFERER#:不允許存取" >     </ cfif > <!--- 判斷參數是否存在 ---> < cfif not isdefined ( "file" )>     < cfthrow type = "Arguments" message = "

Coldfusion (Railo 3.3.4)使用 POI 元件 寫出 XLSX 檔案

圖片
補充前一篇  Coldfusion (Railo 3.3.4) 使用 POI 元件 讀取 xls/xlsx 修改記錄 我在 POIUtility.cfc 內加入一個 Function 用來處理寫出 XLSX 格式檔案 cfc 程式碼(增加): <!--- 自訂寫出 XLSX 的 EXCEL 檔案--->     < cffunction name= "WriteExcelX" access= "public" returntype= "void" output= "false"         hint= "Takes an array of 'Sheet' structure objects and writes each of them to a tab in the Excel file." >         <!--- Define arguments. --->         < cfargument             name= "FilePath"             type= "string"             required= "true"             hint= "This is the expanded path of the Excel file."             />         < cfargument             name= "Sheets"             type= "any"             required= "true"             hint= "This is an array of the data that is needed for each sheet of the excel OR it is a single Sheet object. Each '

Coldfusion (Railo 3.3.4) 使用 POI 元件 讀取 xls/xlsx 修改記錄

圖片
這是配合 上一篇 『 Coldfusion直接讀取/產生Excel檔案 (使用POI元件) 』進階改版 主要原因是 上一篇 的功能只能讀取 XLS檔案,但是對於XLSX卻沒有辦法處理。 如果升級 POI的版本到最新版,會造成 RAILO 內建的 Apache 無法支援該套件版本。 經過一翻苦戰,終於搞定如何處理: 首先,RAILO 3.3.4(註一) 以後因為有支援 cfspreadsheet 指令,所以內建了 POI 套件,但是這個指令僅能處理 XLS 檔案,所以可想而知這個套件是非常陽春的,更不用說要能夠讀取 XLSX 檔案了。

CFLOCK多人共用資源鎖定/獨占

WEB是個多人共用的執行環境。 好處是多人多工執行緒,不會互相干擾。 缺點是同時搶資源時處理上就很傷腦筋。 什麼叫『搶資源』,白話說搶票啦,簡單說就是希望讓多人執行可以排隊做"某件事"。 假如資料庫裡面有一個表Tickets,裡面裡面有500筆資料,每一筆都是獨立票號。 當客人要來取票時,系統會找出Tickets裡面沒有被使用的票號發給客人。 所以程式碼會寫成: <cfquery name="check1" datasource="SQLDB">  Select top 1 tick_no  From Tickets  Where tick_used = 'N' </cfquery> <cfif check1.recordcount GT 0>  <cfset newTicket = check1.tick_no>   <cfquery name="update1" datasource="SQLDB">   Update Tickets   Set tick_used = 'Y' , cust_id = '#LoginCust#'   Where Tick_no = '#newTicket#'  </cfquery> </cfif> <cftransaction action="commit" /> <cfif isdefined("newTicket")>  <cfoutput>You Got Tick No : #newTicket#</cfoutput> <cfelse>  <cfoutput>No More Tickets can get !</cfoutput> </cfif> 邏輯上看似沒有問題,但是請別忘記WEB是多人操作的, 結果就發生同時有2個人很湊巧的同一秒鐘按下取票, 因此上面程式碼就被兩個執行緒同時

Coldfusion直接讀取/產生Excel檔案 (使用POI元件)

圖片
最近在 Ben Nadel 先生的網站發現他有個Component計畫,他利用 apache.org 的 poi project 來製作一個可以讀寫 EXCEL 檔案的 Component,操作 EXCEL 檔真的蠻方便的。而且 poi project 以處理 office文件為目標,算是很棒的專案。 正在想如何直接透過 Coldfusion 網頁處理客戶的 Excel 檔案時,這真是一大幫助啊! 請先參考相關連結: apache.org 的 poi 計畫 、  apache poi jar下載 Ben Nadel 的 POIUtility 文章出處 、 Ben Nadel 的 POIUtility 專案 我的環境 本人使用 Railo 3.3.4.003 執行 Coldfusion ,所以核心是 Apache 比較沒有問題,至於Adobe的Coldfusion可能要再研究一下 Ben Nadel 的專案了。 1、下載  JAR 檔案 注意下載的 poi jar 版本,由於我使用的 Railo 3.3.4.003版本無法搭配最新的 poi,所以測試到使用  poi-3.0-FINAL.jar 是沒有問題的,太新的反而不能用。 把下載的 jar 放在 Railo Server 路徑下的 \lib\ext 裡面,重新啟動服務即完成掛載。 2、下載 Ben Nedal 的 POIUtility.cfc 假設網頁運行路徑在 \webroot\ 你可接放在 \webroot\ 而我的測試是放在 \webroot\COM 裡面 (我個人習慣Component都是放在COM路徑下) 3-1、測試一:讀取全部 首先,建立一個 Excel 檔案 "測試活頁簿.xls",裡面有3個Sheet 3-1.1、寫一段讀取用的 script: <!--- 建立並初始化POI物件 ---> <cfset POIobj = CreateObject("component","COM.POIUtility").Init() > <!--- 取得我要測試的Excel檔案路徑. ---> <cfset myFile

Coldfusion 對 query 語句生成

一般的 query 查詢方式 <cfquery name="QryName" DataSource="ConnecttionName"> SELECT field-A,field-B FROM TableName WHERE strfield = '#sdata#' AND numfield = #ndata# AND dtmfield = #parseDatetime(dtdata)# </cfquery> 上面是純粹帶『查詢資料』進去 Query 語句時所使用的方式,SQL語句屬於固定類的, 但若你把它改成動態語句: <cfset qs = "strfield = '#sdata#' AND numfield = #ndata# AND dtmfield = #parseDatetime(dtdata)#"> <cfquery name="QryName" DataSource="ConnecttionName"> SELECT field-A,field-B FROM TableName WHERE #qs# </cfquery> 這個語句絕對會失敗的, 因為 Coldfusion 為了防止 SQL injection 所以會對 生成 SQL語句的變數裡 ' single-quotation 產生escape 字元,導致生成了不是你想像中的語句。 正確的作法,如果你希望使用動態語句生成,那就是加個指令要求ColdFusion不要去處理 single-quotation 問題即可解決: <cfset qs = "strfield = '#sdata#' AND numfield = #ndata# AND dtmfield = #parseDatetime(dtdata)#"> <cfquery name="QryName" DataSource="ConnecttionName"> SELECT fi

Coldfusion 來自不同資料庫的join作法

Coldfusion server 提供了許多資料庫的Native Connection方式,或是Jconnect的方式,在我認為效率總是比ODBC好多了,所以我寫的網頁常常遊走在不同資料庫上,我最常用的資料庫不外乎Sybase ASE 與 MS SQL (或是更早的MSDE)這兩種資料庫,所以需要用到兩種BD來源的Table需要Join的問題: 這技術需要用到 inMemory Query 的作法就可以達成 首先從各資料庫先取出需要 join 的資料(可以盡量使用篩選過的,減少記憶體用量) <cfquery name="emp" datasource="SYB_CONN"> SELECT empl_no,empl_name,title_no FROM rmployee WHERE depart_no = 'sales' </cfquery> <cftransaction action="commit" /> <cfquery name="ttl" datasource="MSSQL_CONN"> SELECT title_no,title_name FROM outsider_title WHERE title_kind = 'S' </cfquery> <cftransaction action="commit" /> Join 兩邊的資料源 <cfquery name="emptlo" dbtype="query"> SELECT a.empl_name,b.title_name FROM emp a, ttl b WHERE a.title_no = b.title_no </cfquery> 輸出測試 <cfloop query="emptlo"> <cfoutput>#empl_name# , #title_name# <br /></cfou

coldfusion send email (1): only text or html

Coldfusion 發送簡易電子郵件的方法: 使用 cfmail 標籤指令 純文字模式 <cfmail   to="recipient1@mail.domain.com,recipient2@mail.domain.com"   from="sender@mail.mydomain.com"   subject="顧客意見反映"   server="mail.mydomain.com"   username="MySmtpAccount"   password="MyPassword"   type=" text "> 本訊息由網頁『顧客意見』發出,請勿回覆此信件。#chr(13)##chr(10)# 發訊時間 :#DateFormat(NOW() , 'yyyy/mm/dd')# #TimeFormat(NOW() , 'HH:mm:ss')# 發訊人姓名:#SenderName##chr(13)##chr(10)# 發訊人電話:#SenderTEL##chr(13)##chr(10)# 發訊人郵件:#SenderMail##chr(13)##chr(10)# = = = = = = = = = = = = = = = = = = = = #MailBodyText# </cfmail> HTML模式 <cfmail   to="recipient1@mail.domain.com,recipient2@mail.domain.com"   from="sender@mail.mydomain.com"   subject="顧客意見反映"   server="mail.mydomain.com"   username="MySmtpAccount"   password="MyPassword"   type=" html "> <div styl

Coldfusion 多個 query 合併

簡單的用法: <cfquery name="q1" datasource="store1" blockFactor="100">  select * from sales_lists where sale_date = '2013/05/02' </cfquery> <cfquery name="q2" datasource="store2" blockFactor="100">  select * from sales_lists where sale_date = '2013/05/02' </cfquery> <cfquery name="datesales" dbtype="query">  select * from q1  union  select * from q2  order by sale_employee </cfquery> 把多個 DB 查詢用 in memory 查詢 union 起來。 那如果是 LOOP 迴圈連續查詢的 query 呢? 那就讓 query name 不一樣就可以了,然後再用LOOP把query union 起來 <cfloop from="1" to="#ListLen(employeelist)#" index="i">  <cfquery name="qresult#i#" datasource="db1">   select * from employee where employee_no = '#ListGetAt(i)#'  </cfquery> </cfloop> <cfquery name="combine" dbtype="query">   <cfloop fro

Coldfusion Query 的 Commit

最近由coldfusion 操作資料庫查詢時發生的一件事情 在sybase資料庫 做 Replication 的兩部資料庫: A-DB 與 B-DB, 本來,Web-Base的作業都連線在 B-DB 上,App-Base都連在 A-DB上 後來因為B-DB資料區有異常,就把 coldfusion 連線全部連到 A-DB , 接下來,慘事發生了...... A-DB 三不五時發生嚴重 lock ,導致所有作業都停擺,細查原因,發現: 1、全部 lock 都是來自 coldfusion 的 connection ,而且都是 jdbc 驅動連線 2、如果 coldfusion 使用 Sybase 驅動連線,不會發生此現象 3、ColdFusion 不管何種連線到 B-DB 都不太會發生 lock 過久問題 4、Web-Base 的查詢幾乎都是大範圍資料查詢 所以,查了一下設定發現,B-DB 的 lock 範圍強制設定在 row lock等級, Read isolation 屬 uncommit ,這樣的設定應該是為了提高網頁端大量查詢的效率 而 A-DB 屬於內部作業使用有需要極高的正確性,因此屬於page lock等級, Read isolation 屬 commit,因此 App-Base 開發時只要使用到 insert/update 一律要 commit/rollback才能繼續。 以上設定應該是因應公司營業型態調整的 所以,如果在不知道細節的情況下, Coldfusion 的 <cfquery> 指令下完之後 ,無論是Select / Insert / Update 都記得要下一行: <cftransaction action="commit" /> 或是 <cftransaction action="rollback" /> 才不至於出現過度lock狀況,當然這也是比較正統的撰寫習慣 至於 sybase driver connector 與 jdbc driver connector為什麼有不一樣的行為, 應該是差在 select 這個指令,sybase driver 對 select 指令會自動 commit 掉, 但是jdbc d

coldfusion query buildin functions

Method Signiture Return Type Method Signiture Description void queryName.first() jump to the first row of a query void queryName.last() jump to the last row of a query boolean queryName.isFirst() true if we are positioned at the first row boolean queryName.isLast() true if we are positioned at the first row boolean queryName.next() go to the next row, return true if there is a next row boolean queryName.previous() go to the previous row, return true if there is a previous row int queryName.findColumn(String name) get the internal zero based Column ID by name void sort(int columnID, boolean ascending) sort by a column, use findColumn to get the column id String getColumnTypeName(int columnID) gets the data type of a column, this one didn't work properly when I tested it, it would return NUMERIC for a field that was a varchar. There is a method called guessColumnType that was probably used to determine it, it guessed wrong. 資料參考來源

sort query in coldfusion

當我們需要用 coldfusion 查詢資料庫時會使用 cfquery 執行SQL指令 <cfquery name="allEmployee" datasource="myDB">  Select employee_no,employee_name,employee.duty  From employee  Where employee_retired = 'N' </cfquery> 當然,資料排序可以直接下 SQL 的 ORDER BY 來完成 但是,如果有特殊需求需要在 coldfusion 內(in memory)才排序的話 有兩種方式可以完成: 1、使用 cfquery 對已經存在的 query 再處理 <cfquery name="sortedEmployee" dbtype="query">  Select *  From allEmployee  Order By employee_name ASC </cfquery> 2、使用query專用指令 <cfset allEmployee.sort(allEmployee.findColumn("employee_name"),true)> 對於第2種用法,可能要非常小心 因為,adobe的 coldfusion 服務器與 Railo 的服務器有不同的使用法 (注意,我測試的adobe coldfusion 是 MX7,可能新的版本有變) 指令 Adobe Coldfusion MX7 Railo QueryName.sort(QueryName.findColumn("ColumnName"),true) 可 不可 QueryName.sort(2,true) 可 不可 QueryName.sort("ColumnName",true) 不可 可 QueryName.sort("2",true) 不可 不可

使用coldfusion將HTML表格輸出成EXCEL檔案(使用者下載)

Coldfusion 的檔案輸出控制,主要有下面兩個指令 <cfcontent><cfheader> cfcontent 用來告訴瀏覽器等一下要輸出的內容是甚麼格式 cfheader 用來宣告傳輸資料的相關資訊 簡單的輸出測試  saveFileTest.cfm: <cfsetting enablecfoutputonly= "Yes" > <cfcontent type= "application/vnd.ms-excel; charset=big5" > <cfheader name= "Content-Disposition" value= "attachment;filename=ODR10001234567.xls" > <!--- office Excel Format Structure---> <cfoutput> <html xmlns:x= "urn:schemas-microsoft-com:office:excel" > <head> <meta http-equiv= "Content-Type" content= "text/html;charset=big5" > <!--[if gte mso 9]> <xml> <x:ExcelWorkbook> <x:ExcelWorksheets> <x:ExcelWorksheet> <!--- this line names the worksheet ---> <x:Name>訂單狀態</x:Name> <x:WorksheetOptions> <!--- these 2 lines are what works the magic ---> <x:Panes> </x:Panes> </x:WorksheetOptions>

利用 coldfusion 實作 CAPTCHA 驗證功能

圖片
 我當然知道這樣輸入很沒效率,但是這是目前比較好的防廣告文手段。 CAPTCHA,中文常被稱為『驗證碼』,其全名為 Completely Automated Public Turing test to tell Computers and Humans Apart (全自動區分計算機和人類的圖靈測試)。媽呀,好長的名字!!! 需要詳細瞭解者可以看 中文版維基的解釋 或是 英文版本 的。 如果需要輕鬆一點的可以看看 直角兄-淺談各式各樣的網路圖形驗證碼(Captcha) 因為網路上我真的找不太到中文關於使用原生 CFML 來設計 CAPTCHA 驗證碼的文章, 真的有點感嘆,所以就自己動手寫起來以備日後的紀錄與查找。 原始碼出處: http://www.bennadel.com/blog/873-Using-CAPTCHA-In-ColdFusion-8.htm 當然英文看不輪轉的就看我這裡的吧,我已經把註解都中文化,並且稍微修改了一些。

CFSCRIPT是什麼?

來聊一下什麼是 CFSCRIPT 吧: ColdFusion 使用的基礎語言是 CFML ,原文:ColdFusion Markup Language。 意思是 Coldfusion 標記語言,就跟 HTML 一樣屬於標記式 ( tag ) 的程式語法。 相關的資訊可以在 維基網站 查得到,這裡不再多述。 那麼有了 CFML 後為什麼又需要 CFSCRIPT 了呢?

Coldfusion如何使用編/解碼

以下程式碼可能需要 CF9 以上的版本,目前測試 Railo 3.3 可以正常運作。 傳遞資料的時候有時候須要將資料進行編碼或是解碼, 雖然 javascript 可以完成這樣的工作, 但有時候因為隱匿的關係不希望使用者端解譯其運作原理,所以最好是在 Server 端完成。 Coldfusion 可以處理基本的編解碼有三種形式: Hex: use the characters 0-9 and A-F to represent the hexadecimal value of each byte; for example, 3A. UU: use the UNIX UUencode algorithm to convert the data. Base64: use the Base64 algorithm to convert the data, as specified by IETF RFC 2045, at www.ietf.org/rfc/rfc2045.txt . 比較常見的大多是 Base64吧。 以下是完整的測試網頁:

在CFSCRIPT下使用Cookie

Coldfusion繼續來玩Cookie吧, 注意下面的操作可能需要 CF9 以上的版本, Railo 3.3 以上的版本執行上沒有問題。 繼上一篇 Using cookie in CFML 之後,如果想在 Cfscript 中使用cookie的操作要怎麼辦? 目前尋遍 adobe 官方文件 得到的結果是: Direct assignment of Cookie scope memory-only variables. You cannot use direct assignment to set persistent cookies that are stored on the user's system. 真是沒輒!! 但是還是有辦法操作的,就是利用 cf-tag 與 cfscript 混用: 首先,寫一段處理 cookie 的 Function : <cffunction name="setCookie" access="public" returnType="void" output="false">  <cfargument name="name" type="string" required="true">  <cfargument name="value" type="string" required="false">  <cfargument name="expires" type="any" required="false">  <cfargument name="domain" type="string" required="false">  <cfargument name="httpOnly" type="boolean" required="false&q

CFSCRIPT 基本陳述式

這段是給我自己常常忘記如何使用的註記: ColdFusion 的標準 tag 語法法以外,還有 script 語法, 下面是基本的 script 語法使用方式: script語法是包在一個 <cfscript> ... </cfscript> 之間的 每一行指令要用semicolon ; (分號)結尾,但備註與{大括號}結尾不用加 註解方式 //這是單一行的註解 mojo = 1; //這是放在指令後面的註解 /*     這是多行的     註解 */ 設定變數 foo = "foo bar";