2013年2月26日 星期二

[Asp.NET]將數字轉為圖片

最近吵得沸沸揚揚的內政部實價登錄網站,提供各縣市.地區的房價查詢
因為房價透明化,上線第一天就造成大量的流量而造成網路癱瘓
當然今天這篇文章不是在譴責上線沒做好壓力測試,也不是來做房地產分析,
眼尖的人最近應該有發現最近在網站上的價格有些不一樣:
1
用瀏覽器的開發者工具可以發現總價的部分都改為圖片了
2
改成圖片的原因的目的就是政府不讓外界抓到這些統計資料,
進而將這些資料去讓房仲業做出另一個介面提供查詢
當然這邊文章也不是要討論Open Data的相關議題
只因為以前有做過類似的需求,所以來介紹一下數字轉圖片的功能
基本上此功能在C#可以用Graphics這個類別去繪製出來,
我將他寫成一個方法來完成此需求:

private string TransIntToImage(int Number)
   {
       string StrNum = Number.ToString();
       Bitmap Bmp = new Bitmap(StrNum.Length * 80, 25);  //建立實體圖檔並設定大小
       Graphics Gpi = Graphics.FromImage(Bmp);
       MemoryStream stream = new MemoryStream();

       Gpi.Clear(Color.White);    //設定背景顏色
       Font _font = new Font("Verdana", 9, FontStyle.Bold); //設定字型大小.樣式
       for (int i = 0; i < StrNum.Length; i++)
       {
           Int32 j = i * 18;
           Gpi.DrawString(StrNum[i].ToString(), _font, Brushes.Blue, j, 0);
       }
       Bmp.Save(stream, ImageFormat.Jpeg);
       byte[] byteArray = stream.GetBuffer(); //將Bitmap轉為Byte[]
       return Convert.ToBase64String(byteArray); //轉為Base64sting
}

回傳的是一個Base64字串,目的是直接顯示在網頁上,不再另存圖片了:

使用方法如下:
protected void Page_Load(object sender, EventArgs e)
{
    string temp = TransIntToImage(51515);
    img_Number.ImageUrl = "data:image/jpeg;base64," + temp; //直接在網頁上顯示圖片
}

結果顯示:

image



若文章有侵權地方,麻煩請告知,將迅速處理,謝謝!

2013年2月13日 星期三

[Html]Facebook分享連結卻與meta description不一致的情況

一個很蠢的小問題,卻糾纏了1個小時,做個小記錄不要再有人受害~
Facebook近況分享可以貼上影音連結、新聞、等其他外部網站,如下圖:
1
而這些縮圖、標題、內文敘述主要是存在於Html的meta欄位
點選右鍵查看原始碼就可看見:
2
但今天在做本公司網頁時,在FB分享卻存在於舊的資訊,
一看就知道Facebook有cache的機制,網頁修改meta資訊,直接分享還是會存在於舊的
不知道什麼時候這些cache會清掉,但也不能傻傻的等
一開始的解決方式是直接更換檔名,非常的愚蠢XDD
後來才找到Facebook有針對Developers的debug頁面
只要將你更新後的網頁連結,丟上此連結後,
分享過後就會發現是最新修改的資訊了!

2013年2月11日 星期一

[ASP.NET]Html轉成PDF的解決方案

最近遇到一個需求,需要將Html轉成PDF,上網找解決方案找老半天,
不是付費的不然就是匯出後整個版面跑掉,或者是中文亂碼
甚至用過itextsharp這種控制PDF的套件去寫,也不是麼容易T__T
後來發現wkhtmltopdf這個免費的套件,終於解決了我的問題,所以一定要來分享一下!
一開始先至官網下載,依據自己的作業系統下載
1
安裝的話就是一直下一步就對了,
筆者安裝路徑為D:\wkhtmltopdf\wkhtmltopdf.exe
接著我們進入DOS模式去執行程式
2
3
第一個黃框為執行檔的位置
第二個黃框為轉檔目標的URL
第三個黃框為PDF儲存的位置
接著執行就直接進行轉換了:
image
目前測試效果還不錯,如果是中文字的話,記得要在編碼設定為utf-8
不然轉換後都會是亂碼!
接著我們自己寫程式執行吧!
基本上大同小異,只是利用Process這個類別去執行它而已:
protected void Page_Load(object sender, EventArgs e)
{
    Process _process = new Process();
    _process.StartInfo.FileName = @"D:\wkhtmltopdf\wkhtmltopdf.exe";
    _process.StartInfo.Arguments = @"http://www.google.com.tw D:\temp2.pdf";
    _process.Start();
}

如果你要在產生過後,對這個PDF檔案做一些處理(例如開啟此檔案),

必須要等這個執行續完成,不然會出錯,可以用以下方法:
Process _process = new Process();
_process.StartInfo.FileName = @"D:\wkhtmltopdf\wkhtmltopdf.exe";
_process.StartInfo.Arguments = @"http://www.google.com.tw D:\temp2.pdf";
_process.Start();

while (_process.HasExited)
{
    //讓執行續暫停1秒
    Thread.Sleep(1000);
}

Process.Start(@"D:\temp2.pdf");

這樣就完成了,其實他還有很多姊妹作,像是HtmlToImage

有機會再分享囉!

相關文章:

http://brooky.cc/2011/05/26/convert-html-to-image-and-pdf/

http://code.google.com/p/wkhtmltopdf/

http://www.cnblogs.com/heblade/archive/2009/10/16/Html_to_pdf.html

2013年2月7日 星期四

[MS SQL]將多筆資料合併欄位,減少不必要的連線

之所以會有這篇文章,是最近在改寫公司老舊的ASP報表

主要的邏輯是撈出全部資料後,逐筆判斷該資料在另一個Table是否有相似的資料

如果有則Response出來,秀在此筆資料的下方,但如此簡單的邏輯,卻要Run很久才能跑出來

仔細看他的寫法是這樣,我以C#改寫,以使用者登入紀錄為例,我建了兩個資料表:


使用者資料表
登入紀錄資料表
1 2

當然這裡舉例的不是那麼恰當,登入紀錄應該是記錄到時分秒單位

重點是在下面這段程式:


string connString = WebConfigurationManager.ConnectionStrings["TestDBconn"].ConnectionString;
SqlConnection conn = new SqlConnection(connString);
SqlCommand cmd = new SqlCommand();
cmd.Connection = conn;

string Sql_User = "select * from [User]";
SqlDataAdapter da = new SqlDataAdapter(Sql_User, conn);
DataTable dt = new DataTable();
da.Fill(dt);
if (dt.Rows.Count > 0)
{
    for (int i = 0; i < dt.Rows.Count; i++)
    {
        //依使用者撈出登入紀錄
        string Sql_Login = "select * from LoginRecord where UserID = " + dt.Rows[i]["sn"].ToString();
        da = new SqlDataAdapter(Sql_Login, conn);
        DataTable dt_login = new DataTable();
        da.Fill(dt_login);
        if (dt_login.Rows.Count > 0)
        {
            for (int k = 0; k < dt_login.Rows.Count; k++)
            {
                /* 
                 * Show Login Data . . . . .
                 */
            }
        }
    }
}

乍看之下結果沒什麼問題,但很可怕的是逐筆連線去執行select

因如果資料可能上千上萬,甚至DB是用 Link Server的方式,

原本連線要兩秒這樣加下來就會Run到天荒地老

接著就會換來使用者的一句,程式怎麼寫那麼爛Q_Q

所以將這支程式做一點改寫,使用SQL的for XML Path語法

3

現在已經把該使用者登入紀錄全篩到一個新的欄位LoginData,

但這樣還是不太好閱讀,故我們用一些小技巧,把它轉為varchar

並用逗號分隔,再用Substring去除開頭的逗號:

4

如此已經完成抓出每個使用者的登入紀錄了,

接下來只要把這個子查詢,加入主表裡就改寫成功了:

5



經過這樣改寫已經把連線此數降為1次,

接下來只需要在程式裡用Split切割逗號,去秀出要的資料,

這種寫法應該是程式老手不太會犯的錯誤,

活生生的案例在實務上遇到了,也許一開始資料量小沒care這麼多

但還是養成code review的習慣以免害到後人阿!