不過客戶還是想要有個按鈕能讓圖片下載
所以坎尼只好再想辦法滿足客戶的需求
UI設定
首先,在畫面上準備好下載按鈕和圖表順便設定一下樣式和內容,這部分之前講過很多次就不多談了
撰寫按鈕事件
先宣告 System.IO.MemoryStream 物件,用來承接 Chart 的 binary 資料再利用 Chart.SaveImage 方法將資料流放到 MemoryStream 中
把 Stream 轉為 byte[] 陣列後,再丟到匯出的方法中處理
Chart.SaveImage 儲存方式有兩種:FilePath 及 Stream
但用 FilePath 的方式是儲存在 Server 端,要另外再多做個動作才能讓使用者下載
所以坎尼就選用 Stream 來處理
接著是匯出 byte[] 裡的二進位資料
這邊坎尼是參考董大偉老師的 如何在ASP.NET中下載檔案
另外函式做了點小修改,也可以用來匯出其他二進位的資料流
執行程式,點下載圖片後會直接將圖片匯出
噹噹噹噹噹,圖片就這樣下載到使用者的電腦上啦
此次的範例檔下載
小結
上面有講到明明右鍵就可以下載,但為什麼還要弄個按鈕出來,是要累死工程師嗎?最近坎尼有看到一篇 Web Design 的文章講的很好
(原文是英文,坎尼大致上翻譯一下意思)
「盡量把操作弄成最愚笨的方式,使用者會比較容易使用」
「但仍要保留給進階使用者進階技巧的使用權利,他們會希望用一組快速鍵達到滑鼠點三次的要求」
所以設計者們,記得有機會就多留點隱藏技巧,令使用者有驚喜的感覺
不過不要留了後門給駭客進出啊 XDDDD
21 則留言:
供獻點小技巧... 其實不用透過 MemoryStream 啦,直接存到 Response.OutputStream 也可以..
感謝 chicken 大大提供意見
不過剛剛坎尼照 MSDN 上的 Response.OutputStream範例去測,怎麼都做不出來 Orz
一開始是想把 OutputStream 丟到 byte[] 裡,可是取 length 的時候就發生例外了
再來是照範例:設定 ContentType 後,呼叫SaveImage寫到 OutputStream 後直接 Response.Flush()
但目前還是測不出來
chicken大可以指點一下嗎? 感謝 ^^
突然想到,你大概踩到一個地雷了... 你是輸出 PNG 格式嗎? 會 GDI+ error...
我貼一下我測的 sample code 片段:
Response.ContentType = "image/jpeg";
Chart1.SaveImage(Response.OutputStream, ChartImageFormat.Jpeg);
這兩行就搞定了。不過格式不指定的話,預設是 PNG,它輸出的 OutputStream 必需要能夠 SEEK,不過.. Response.OutputStream 不支援,只能讓你一路一直寫下去...
運氣還不錯,JPEG 輸出就沒這限制,不在乎圖檔髒一點的話,就用JPEG吧 :D
不然推薦另一個作法,用 MemoryStream 碰到大圖大概會吃掉一堆 memory, 不如輸出成暫存檔,用 Response.TransmitFile( ) 來輸出檔案,可以避開單一頁面載入過多 memory 的問題
還真是踩到 png 這個地雷,囧rz
JPEG 出來的圖是真的蠻醜的
看來還是把檔案存在 Server 上,再把圖檔送給 user 下載會是比較好的作法
但這就要記得定期去清空 Server 上Create的暫存圖檔,以免Server的空間被偷偷吃掉
您好:
請問一下,為什麼我匯出時的圖檔是空白的?
hello 匿名你好,
先確認一下你的 Chart 是否有開啟 ViewState?
EnableViewState=true
若是沒有開啟 ViewState,記得在匯出圖片前,再讓 Chart 重新 Render 圖片
本篇有附範例檔,可以把範例下載下來參考一下 ^^
坎尼兄:
謝謝你,依據你所說明的,已經可以了!
不好意思, 請教一下, chart control 製作的圖, 可以匯出在 Excel 嗎?
hi mo,
理論上應該是可以,不過坎尼沒實作這部份,倒是不敢向你保證
剛好接下來的那篇會講 Excel 匯出
坎尼就順便測試看看
作法的流程可能為:
1.圖片存在 Server 端,將圖片路徑內嵌於 Excel 中
2.圖片存為 binary 方式,再用 excel xml 的方式匯出
以上是目前想到的進行方式,有實作出來的讀者也可以交換一下心得 ^^
hi mo,
已經有將圖片匯出至 Excel 的文章
請參考 http://dotnetmis91.blogspot.com/2010/03/chart-control-excel-npoi.html
Response.ContentType = "image/jpeg";
Chart1.SaveImage(Response.OutputStream, ChartImageFormat.Jpeg);
請問我執行的結果會變成在網頁上show(_self的方式),而不是出現下載視窗,請問是為什麼呢,謝謝
上面沒打好,不好意思@@
執行的結果會變成直接在網頁上show出jpg圖片,而不是出現下載視窗,請問是為什麼呢,謝謝
hi 匿名,
請問你圖片的 binary 資料流,有經過範例中的 ExportStream() 方法處理嗎?
這方法是把原本直接在畫面上顯示的動作,改為檔案下載的方式 (修改 html header)
若非如此,請麻煩再提供更詳細的資訊 ^^
坎尼大你好,
我確實少了ExportStream()步驟,
現在已可正常下載圖片了,謝謝你的指導~
坎尼大你好,
想下載你提供的範例檔,但無法下載。不知是否有機會可以下載該範例
hi 初學者,
本篇範例坎尼看來是找不到了 orz
本文重點 source code 都有抓圖且有說明,先自行試著照做看看~
這個範例不難,如果有遇到問題再發問吧
謝謝坎尼大的幫忙^__^
HI 這按鈕好像一次只能抓一張
如果網頁上有5張CHART 討厭的客戶想要有個按鈕 按一下 就把這5張圖下載下來 請問該怎麼做呢? THX
hi usein,
一次要下載5張, 只要重覆做 btnDownloadPicture_Click 裡的動作 (用迴圈把 Chart1~Chart5 各跑過一次)
如果想要壓縮成 zip,可以去查 System.IO.Compression Namespace 裡的 class,把 5 張圖片一次打包給客戶
hi 坎尼大大
我照您的方法下去試驗,有下載圖下來,但是Chart上有外框沒內容,有我chart的標頭,EnableViewState=true <<這也設定了。
可以請大大幫我嗎?
我的資料是用datatable做繫結的
DataTable M1_C = this.queryDataTable("M1_ZERO", "CLAMP");
Chart1.DataSource = M1_C;
Chart1.DataBind();
痾.....坎尼大大
我解掉了.....SORRY,犯了個超級笨的錯誤。
抱歉阿~~~~^^
張貼留言