前端網頁利用HighCharts.js畫圖表的強大,我就不再贅述。

反而今天要提到的是他的弱點:「圖表檔名匯出中文..會變亂碼」。

HighCharts的預設匯出功能在圖表右上角,如下圖↓

p1

 

圖表的預設檔名都是chart,由於是英文所以匯出都ok。

但若將檔名自定義為中文的話,匯出會變成下圖中的亂碼,於是就多了一個任務要解了。

p2  

查了官網中這篇文章有提到,官方並無支援各國語言包或套件,而在匯出時是使用exporting.js裡將圖表以svg的方式POST到官方指定的接口。

想要支援各國語言,就得自行準備一個POST接口,裡面使用UTF-8編碼後response吐出圖表才可以實現匯出中文檔名。

exporting.js其中有一段是:

//url:"http://export.highcharts.com/"
//改替換呼叫自己準備的接口url
url:"/HighChartsExtend/HighCharts"

 

在這裡我是用ASP.NET MVC4開發環境,所以範例就新建一個Controller,準備來寫Exporting的接口。

public class HighChartsExtendController : Controller
    {
        //若要使用此自訂義HighCharts匯出圖檔,在exporting.js中要置換url:"http://export.highcharts.com/"/*"/HighChartsExtend/HighCharts"*/
        [ValidateInput(false)]
        public ActionResult Highcharts(string fileName, string type, int width, string svg, string scale)
        {

            if (Request.Unvalidated.Form["type"] != null && Request.Unvalidated.Form["svg"] != null && Request.Unvalidated.Form["filename"] != null)
            {
                string tType = Request.Unvalidated.Form["type"].ToString();
                string tSvg = Request.Unvalidated.Form["svg"].ToString();
                string tFileName = Request.Unvalidated.Form["filename"].ToString();
                int tScale = int.Parse(Request.Unvalidated.Form["scale"].ToString());
                if (tFileName == "")
                {
                    tFileName = "chart";
                }
                MemoryStream tData = new MemoryStream(Encoding.UTF8.GetBytes(tSvg));
                MemoryStream tStream = new MemoryStream();
                string tTmp = new Random().Next().ToString();

                string tExt = "";
                string tTypeString = "";

                switch (tType)
                {
                    case "image/png":
                        tTypeString = "-m image/png";
                        tExt = "png";
                        break;
                    case "image/jpeg":
                        tTypeString = "-m image/jpeg";
                        tExt = "jpg";
                        break;
                    case "application/pdf":
                        tTypeString = "-m application/pdf";
                        tExt = "pdf";
                        break;
                    case "image/svg+xml":
                        tTypeString = "-m image/svg+xml";
                        tExt = "svg";
                        break;
                }

                if (tTypeString != "")
                {
                    string tWidth = Request.Unvalidated.Form["width"].ToString();
                    Svg.SvgDocument tSvgObj = SvgDocument.Open(tData);
                    tSvgObj.Transforms.Add(new Svg.Transforms.SvgScale(tScale, tScale));
                    tSvgObj.Width *= tScale;
                    tSvgObj.Height *= tScale;
                    
                    switch (tExt)
                    {
                        case "jpg":
                            tSvgObj.Draw().Save(tStream, ImageFormat.Jpeg);
                            break;
                        case "png":
                            tSvgObj.Draw().Save(tStream, ImageFormat.Png);
                            break;
                        case "pdf":
                            PdfWriter tWriter = null;
                            Document tDocumentPdf = null;
                            try
                            {
                                tSvgObj.Draw().Save(tStream, ImageFormat.Png);
                                tDocumentPdf = new Document(new Rectangle((float)tSvgObj.Width, (float)tSvgObj.Height));
                                tDocumentPdf.SetMargins(0.0f, 0.0f, 0.0f, 0.0f);
                                iTextSharp.text.Image tGraph = iTextSharp.text.Image.GetInstance(tStream.ToArray());
                                tGraph.ScaleToFit((float)tSvgObj.Width, (float)tSvgObj.Height);

                                tStream = new MemoryStream();
                                tWriter = PdfWriter.GetInstance(tDocumentPdf, tStream);
                                tDocumentPdf.Open();
                                tDocumentPdf.NewPage();
                                tDocumentPdf.Add(tGraph);
                                tDocumentPdf.CloseDocument();
                            }
                            catch (Exception ex)
                            {
                                throw ex;
                            }
                            finally
                            {
                                tDocumentPdf.Close();
                                tDocumentPdf.Dispose();
                                tWriter.Close();
                                tWriter.Dispose();
                                tData.Dispose();
                                tData.Close();

                            }
                            break;

                        case "svg":
                            tStream = tData;
                            break;
                    }

                    Response.ClearContent();
                    Response.ClearHeaders();
                    Response.ContentType = tType;
                    Response.AppendHeader("Content-Disposition", "attachment; filename=" + tFileName + "." + tExt + "");
                    Response.BinaryWrite(tStream.ToArray());
                    Response.End();
                }
            }
            return null;
        }
    }

最後在此Controller必需載入2個額外的dll檔,這在Nuget上都找的到。

itextsharp

Svg Rendering Library

以上,就大功告成了!


arrow
arrow

    pinylnln 發表在 痞客邦 留言(0) 人氣()