Canvas畫好的圖片雖然可以通過toDataURL()轉成二進制流的字符串格式,圖片稍大一點就無法發送了,當然如果需求簡單的話,可以在頁面上加一個image元素,將轉成的流直接賦給image的src就可以顯示圖片了。
但是大部分的時候我們還希望彈出保存框,保存圖片到我們自己想要的路徑下,或者添加一些統計和分析的信息到pdf中一起保存成一個pdf文件,這就需要在後台處理了,兩種方式:後台新建一個Web Browser加載當前的頁面,然後將獲得到的圖片流的信息再發送到前台彈出保存的對話框,後台發送到前台是沒有字符長度的限制的,不過這種辦法就是如果保存成pdf,他是要截圖然後放到pdf中,圖片太長就截斷了;另外一種方式就是將用到的參數傳到後台,後台用GDI+在Bitmap上重新畫一遍,Canvas能實現的,後台的GDI+同樣都能實現,而且有些實現可能更方便一些,這個方法的好處是,沒有圖片大小的限制。
我最近做得一個項目用的是第二種方法實現的,貼下代碼吧:
1、前台代碼【點擊保存圖片按鈕】:
var width = drawObject.getCanvas().width; var height = drawObject.getCanvas().height; var figures = drawObject.getCurrentFigures(); $.ajax( { url: "./WareHousePrintHandler.ashx?action=drawpng&width=" + width + "&height=" + height, type: "post", data: "datas=" + JSON.stringify(figures), success: function (fileName) { $('#frameImage').attr('src', "./WareHousePrintHandler.ashx?action=getpng&fileName=" + fileName); }, error: function (err) { alert("Print failed."); } });
將前台需要畫圖的信息通過ajax傳到後台的一個handler中,handler負責接收參數,並且將畫好的圖片保存至某個IIS的共享路徑下,圖片名稱返回到前台,前台再用一個大小為0的iframe去通過重新加載頁面,通過此圖片名稱去後台取圖片流並彈出保存提示框。
2、iframe的代碼
<iframe width="0" height="0" id="frameImage" name="frameImage" frameborder="0" scrolling="no"></iframe>
3、後台代碼
if (action.ToString() == "drawpng") { if (context.Request["datas"] == null) { return; } double w = double.Parse(context.Request["width"].ToString()); double h = double.Parse(context.Request["height"].ToString()); string allFigures = context.Server.UrlDecode(context.Request["datas"].ToString()); ListfigureList = AspSoft.WareHouse.Util.JsonHelper.JsonDeserialize >(allFigures); WareHouseDrawing drawing = new WareHouseDrawing(); string fileName = drawing.GetImageUrl((int)w, (int)h, figureList, filePath); context.Response.Write(fileName); //ms.WriteTo(Response.OutputStream); context.Response.End(); } else if (action.ToString() == "getpng") { string fileName = context.Request["fileName"].ToString(); string fullFileName = filePath + "/" + fileName; context.Response.AppendHeader("Content-Disposition", string.Format("Attachment; FileName={0}.png;", HttpUtility.UrlEncode(DateTime.Now.ToString("yyyyMMdd_HHmmss"), System.Text.Encoding.UTF8))); context.Response.WriteFile(fullFileName); context.Response.End(); }
GetImageUrl是具體畫的方法,將畫好的圖片保存到一個共享路徑下,必須是IIS能訪問的共享路徑,不能是本地的路徑,第二次請求是獲得png,實際是獲得png的路徑,iframe加載圖片的路徑後會自動獲得圖片的流信息,這是浏覽器自動處理的,這裡關鍵的是要加上Attachment,要以附件的形式發送。
此方法必須發送兩次請求到後來才能完成,因為如果第一次就通過iframe的src方式請求圖片,由於只能通過querystring的方式請求,不能傳大的數據,因為需要畫圖的數據量也是比較大,必須先通過ajax請求。PDF的道理同上,就是將bitmap的信息放到PDF中就可以了。