CODE-Canvas.toDataURL()另存檔案
3 | 28,386 |
在HTML5 Canvas塗鴉板裡,雖然提供了匯出圖檔功能,卻必須由使用者自行在網頁的圖檔上按右鍵另存檔案,只能算半自助的服務。理想做法應比照一般網頁下載操作,在按鈕後直接跳出存檔提示,讓使用者決定存檔位置及檔名等,較符合一般使用者期望。
我在網路上找到Jacob Seidelin實作的cavas2imgage.js程式庫,追了一下程式碼發現是透過location.href = DataURI字串實現由Javascript觸發瀏覽器直接下載檔案,但我發現它有一些缺點: 一來無法指定檔案名,二來並不適用全部的瀏覽器。看來還是得仰賴伺服器端的"內應",才能達到較好的效果。
這點小事自然難不倒ASP.NET,以下便是伺服器端內應的範例(DownloadImage.ashx)。運作流程包含兩個階段,要下載圖檔時,先透過jQuery.post()將DataURI字串送至ASP.NET端,再由C#程式將其還原成byte[]存入Cache,並動態產生一個GUID為Cache Key傳回Javascript端;前端在取得GUID Key後,即可以location.href = "DownloadImageFile.ashx?k=" + GUIDKey的方式再度呼叫ASP.NET程式,此時再透過傳入的GUID由Cache取出byte[],以檔案下載MIME Type(application/octect-stream)並指定以下載時間決定的檔案名傳回PNG圖檔。由於此作業僅為一次性,在下載完成後即可將Cache內的資料清除,節省空間。
排版顯示純文字
<%@ WebHandler Language="C#" Class="DownloadImage" %>
using System;
using System.Web;
using System.Web.Caching;
public class DownloadImage : IHttpHandler {
public void ProcessRequest (HttpContext context) {
HttpRequest req = context.Request;
HttpResponse resp = context.Response;
try
{
if (req.HttpMethod == "POST")
{
string header = "data:image/png;base64,";
string data = req.Form["data"];
//檢查上傳內容為PNG Data URI才處理
if (data.StartsWith(header))
{
//隨機產生GUID
string k = Guid.NewGuid().ToString();
//將Data URI轉成byte[]以GUID為Key存內Cache
HttpContext.Current.Cache.Add(k,
Convert.FromBase64String(data.Substring(header.Length)),
null, DateTime.Now.AddSeconds(60),
Cache.NoSlidingExpiration, CacheItemPriority.High, null);
//回傳GUID
resp.Write(k);
}
}
else if (req.HttpMethod == "GET")
{
string k = req.QueryString["k"];
//由前方傳入Key參數提取Cache中的資料
if (HttpContext.Current.Cache[k] != null)
{
//以檔案下載方式回傳byte[]內容
resp.AddHeader("content-disposition",
string.Format("attachment;filename={0:yyyyMMddHHmmss}.png", DateTime.Now));
resp.ContentType = "application/octet-stream";
resp.BinaryWrite((byte[])HttpContext.Current.Cache[k]);
//清除Cache中的內容
HttpContext.Current.Cache.Remove(k);
}
}
}
catch (Exception ex)
{
resp.ContentType = "text/plain";
resp.Write(ex.Message);
}
}
public bool IsReusable {
get {
return false;
}
}
}
下載圖檔功能所需的Script也很簡單,不用五行就能打發:
排版顯示純文字
$("#bDownload").click(function () {
$.post("DownloadImage.ashx", { data: $canvas[0].toDataURL() },
function (k) {
if (k)
location.href = "DownloadImage.ashx?k=" + k;
});
});
備有線上展示,有興趣的人可以動手玩玩。
Comments
# by 黃蜂
請問: 在網路上找到Jacob Seidelin實作的cavas2imgage.js程式庫。 指的是這個嗎? https://github.com/hongru/canvas2image 如果是,那就是改網址了。
# by Jeffrey
to 黃蜂,你找到的應是其他人的版本,Jacob Seidelin的github在https://github.com/jseidelin 。nihilogic.dk網站目前是壞的,我找到一個備份 http://www.jsdelivr.com/#!canvas2image
# by 黃蜂
感謝 Jeffrey 回覆,您的部落格幫助我很多。