CODE-Canvas.toDataURL()另存檔案
| | | 3 | |
在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 回覆,您的部落格幫助我很多。