highcharts 的Net导出服务 GitHub上整理的https://github.com/imclem/Highcharts-export-module-asp.net
引用两个程序集 sharpPDF.dll,Svg.dll (实际上就是将svg转化成其他格式的图片)
两种导出情况:
1、只需要图片,修改自带导出按钮的请求路径路径就行
2、需要插入到word等二次处理再导出时
页面:
@{ ViewBag.Title = "Index"; } @section css{ } @section scripts{ <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script> <script src="/Scripts/Highcharts-4.0.4/js/highcharts.js"></script> <script src="/Scripts/Highcharts-4.0.4/js/highcharts-more.js"></script> <script src="/Scripts/Highcharts-4.0.4/js/modules/exporting.js"></script> <script type="text/javascript"> var chart; $(function () { var datas = { chart: { zoomType: 'xy' }, title: { text: 'Temperature vs Rainfall' }, xAxis: [{ categories: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'] }], yAxis: [{ // Primary yAxis labels: { format: '{value} °C', style: { color: Highcharts.getOptions().colors[1] } }, title: { text: 'Temperature', style: { color: Highcharts.getOptions().colors[1] } } }, { // Secondary yAxis title: { text: 'Rainfall', style: { color: Highcharts.getOptions().colors[0] } }, labels: { format: '{value} mm', style: { color: Highcharts.getOptions().colors[0] } }, opposite: true }], tooltip: { shared: true }, exporting: { url: '/HighCharts/Export', //1、自带导出按钮的请求路径 filename: 'MyChart', 1200 }, series: [ { name: 'Temperature', type: 'spline', data: [7.0, 6.9, 9.5, 14.5, 18.2, 21.5, 25.2, 26.5, 23.3, 18.3, 13.9, 9.6], tooltip: { pointFormat: '<span style="font-weight: bold; color: {series.color}">{series.name}</span>: <b>{point.y:.1f}°C</b> ' } }, { name: 'Temperature error', type: 'errorbar', data: [[6, 8], [5.9, 7.6], [9.4, 10.4], [14.1, 15.9], [18.0, 20.1], [21.0, 24.0], [23.2, 25.3], [26.1, 27.8], [23.2, 23.9], [18.0, 21.1], [12.9, 14.0], [7.6, 10.0]], tooltip: { pointFormat: '(error range: {point.low}-{point.high}°C)<br/>' } } , { name: 't2===========', type: 'spline', data: [118.3, 13.9, 7.0, 6.9, 9.5, 14.5, 18.2, 21.5, 25.2, 26.5, 23.3, 9.6], tooltip: { pointFormat: '<span style="font-weight: bold; color: {series.color}">{series.name}</span>: <b>{point.y:.1f}°C</b> ' } }, { name: 't2============ error', type: 'errorbar', data: [[118.0, 121.1], [12.9, 14.0], [6, 8], [5.9, 7.6], [9.4, 10.4], [14.1, 15.9], [18.0, 20.1], [21.0, 24.0], [23.2, 25.3], [26.1, 27.8], [23.2, 23.9], [7.6, 10.0]], tooltip: { pointFormat: '(error range: {point.low}-{point.high}°C)<br/>' } } ] }; $('#container-Test').highcharts(datas); $('#container-Test2').highcharts(datas); }); // 2、插入到word等二次处理导出时用到 //点击一个按钮导出图片 function exportClick() { var chartTest = $('#container-Test').highcharts(); var svgData = chartTest.getSVG(); $.post('/HighCharts/ManualExport', { filename: "手动导出的图片", type: "image/png", 1200, svg: svgData }, function (r) { if (!r.state) return; window.location.href = r.downloadpath; },'json'); } </script> } <h2>Index</h2> <div> <input type="button" value="点击一个按钮导出图片" onclick="exportClick()"/> </div> <div id="container-Test" style="height: 400px; margin: auto; min- 310px; max- 600px"></div> <hr /> <div id="container-Test2" style="height: 400px; margin: auto; min- 310px; max- 600px"></div>
控制器:
using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Timers; using System.Web; using System.Web.Mvc; using Newtonsoft.Json; using xxoo.Common.HighChart; namespace ToolsSite.Controllers { public class HighChartsController : Controller { // // GET: /HighCharts/ public ActionResult Index() { return View(); } #region1、 自带的导出按钮 //修改 HighChart 导出服务器路径 //exporting: { url: '/HighCharts/Export', filename: 'MyChart', 1200 }, [ValidateInput(false)] [HttpPost] public ActionResult Export(string filename, string type, int width,string svg) { Exporter export = new Exporter(filename, type, width, svg); //// 1、文件名输出 //FileStream fileWrite = new FileStream(@"d:HighCharts导出图片.png", FileMode.Create, FileAccess.Write); //ExportFileInfo fi = export.WriteToStream(fileWrite); //string fileName = "导出的图片." + fi.Extension; //fileWrite.Close(); //fileWrite.Dispose(); //return File(@"d:HighCharts导出图片.png", fi.ContentType, fileName); // 2、 字节输出 ExportFileInfo fi; byte[] buffer = export.WriteToBuffer(out fi); string fileName = "导出的图片." + fi.Extension; return File(buffer, fi.ContentType, fileName); } #endregion #region 2、 点击一个按钮导出图片 (插入到word等二次处理导出时用到) [ValidateInput(false)] [HttpPost] public ActionResult ManualExport(string filename, string type, int width, string svg) { Exporter export = new Exporter(filename, type, width, svg); string fileId = Guid.NewGuid().ToString(); string tempFilePath = Request.MapPath("~/DownFile/") + fileId; // 1、文件名输出 FileStream fileWrite = new FileStream(tempFilePath, FileMode.Create, FileAccess.Write); ExportFileInfo fi = export.WriteToStream(fileWrite); filename += "." + fi.Extension; fileWrite.Close(); fileWrite.Dispose(); Timer tr = new Timer(1000 * 60 * 1); // 1分钟后删除 tr.Elapsed += (s, e) => { if (System.IO.File.Exists(tempFilePath)) { System.IO.File.Delete(tempFilePath); } }; tr.Start(); string downloadPath = string.Format( "/HighCharts/ManualDownload?fileId={0}&ContentType={1}&fileName={2}" , fileId,fi.ContentType, filename); var o = new { state = true, downloadpath = downloadPath }; string result = JsonConvert.SerializeObject(o); return Content(result); } // 手动下载导出文件 [HttpGet] public ActionResult ManualDownload(string fileId, string ContentType,string fileName) { string tempFilePath = Request.MapPath("~/DownFile/") + fileId; if (!System.IO.File.Exists(tempFilePath)) { return Redirect("/HighCharts/Index?msg=文件已失效"); } byte[] buffer = System.IO.File.ReadAllBytes(tempFilePath); System.IO.File.Delete(tempFilePath); return File(buffer, ContentType, fileName); } #endregion } }
工具类:
using System; using System.Collections.Generic; using System.Drawing; using System.Drawing.Imaging; using System.IO; using System.Linq; using System.Text; using System.Web; using sharpPDF; using Svg; using Svg.Transforms; namespace xxoo.Common.HighChart { /// <summary> /// Processes web requests to export Highcharts JS JavaScript charts. /// </summary> internal static class ExportChart { /// <summary> /// Processes HTTP Web requests to export SVG. /// </summary> /// <param name="context">An HttpContext object that provides references /// to the intrinsic server objects (for example, Request, Response, /// Session, and Server) used to service HTTP requests.</param> internal static void ProcessExportRequest(HttpContext context) { if (context != null && context.Request != null && context.Response != null && context.Request.HttpMethod == "POST") { HttpRequest request = context.Request; // Get HTTP POST form variables, ensuring they are not null. string filename = request.Form["filename"]; string type = request.Form["type"]; int width = 0; string svg = request.Form["svg"]; if (filename != null && type != null && Int32.TryParse(request.Form["width"], out width) && svg != null) { // Create a new chart export object using form variables. Exporter export = new Exporter(filename, type, width, svg); // Write the exported chart to the HTTP Response object. export.WriteToHttpResponse(context.Response); // Short-circuit this ASP.NET request and end. Short-circuiting // prevents other modules from adding/interfering with the output. HttpContext.Current.ApplicationInstance.CompleteRequest(); context.Response.End(); } } } internal static void ProcessExportRequest(string filename, string type, string svg,string widthStr,Stream stream) { // Get HTTP POST form variables, ensuring they are not null. int width = 0; if (filename != null && type != null && Int32.TryParse(widthStr, out width) && svg != null) { // Create a new chart export object using form variables. Exporter export = new Exporter(filename, type, width, svg); // Write the exported chart to the HTTP Response object. export.WriteToStream(stream); // Short-circuit this ASP.NET request and end. Short-circuiting // prevents other modules from adding/interfering with the output. HttpContext.Current.ApplicationInstance.CompleteRequest(); HttpContext.Current.Response.End(); } } } /// <summary> /// 导出的文件信息 /// </summary> internal class ExportFileInfo { /// <summary> /// 文件扩展名 /// </summary> public string Extension { get; set; } /// <summary> /// 响应输出文件类型 /// </summary> public string ContentType { get; set; } } /// <summary> /// .NET chart exporting class for Highcharts JS JavaScript charts. /// </summary> internal class Exporter { /// <summary> /// Default file name to use for chart exports if not otherwise specified. /// </summary> private const string DefaultFileName = "Chart"; /// <summary> /// PDF metadata Creator string. /// </summary> private const string PdfMetaCreator = "Tek4(TM) Exporting Module for Highcharts JS from Tek4.com"; /// <summary> /// Gets the HTTP Content-Disposition header to be sent with an HTTP /// response that will cause the client's browser to open a file save /// dialog with the proper file name. /// </summary> public string ContentDisposition { get; private set; } /// <summary> /// Gets the MIME type of the exported output. /// </summary> public string ContentType { get; private set; } /// <summary> /// Gets the file name with extension to use for the exported chart. /// </summary> public string FileName { get; private set; } /// <summary> /// Gets the chart name (same as file name without extension). /// </summary> public string Name { get; private set; } /// <summary> /// Gets the SVG chart document (XML text). /// </summary> public string Svg { get; private set; } /// <summary> /// Gets the pixel width of the exported chart image. /// </summary> public int Width { get; private set; } /// <summary> /// Initializes a new chart Export object using the specified file name, /// output type, chart width and SVG text data. /// </summary> /// <param name="fileName">The file name (without extension) to be used /// for the exported chart.</param> /// <param name="type">The requested MIME type to be generated. Can be /// 'image/jpeg', 'image/png', 'application/pdf' or 'image/svg+xml'.</param> /// <param name="width">The pixel width of the exported chart image.</param> /// <param name="svg">An SVG chart document to export (XML text).</param> internal Exporter( string fileName, string type, int width, string svg) { string extension; this.ContentType = type.ToLower(); this.Name = fileName; this.Svg = svg; this.Width = width; // Validate requested MIME type. switch (ContentType) { case "image/jpeg": extension = "jpg"; break; case "image/png": extension = "png"; break; case "application/pdf": extension = "pdf"; break; case "image/svg+xml": extension = "svg"; break; // Unknown type specified. Throw exception. default: throw new ArgumentException( string.Format("Invalid type specified: '{0}'.", type)); } // Determine output file name. this.FileName = string.Format( "{0}.{1}", string.IsNullOrEmpty(fileName) ? DefaultFileName : fileName, extension); // Create HTTP Content-Disposition header. this.ContentDisposition = string.Format("attachment; filename={0}", this.FileName); } /// <summary> /// Creates an SvgDocument from the SVG text string. /// </summary> /// <returns>An SvgDocument object.</returns> private SvgDocument CreateSvgDocument() { SvgDocument svgDoc; // Create a MemoryStream from SVG string. using (MemoryStream streamSvg = new MemoryStream( Encoding.UTF8.GetBytes(this.Svg))) { svgDoc = SvgDocument.Open<SvgDocument>(streamSvg); } // Scale SVG document to requested width. svgDoc.Transforms = new SvgTransformCollection(); float scalar = (float)this.Width / (float)svgDoc.Width; svgDoc.Transforms.Add(new SvgScale(scalar, scalar)); svgDoc.Width = new SvgUnit(svgDoc.Width.Type, svgDoc.Width * scalar); svgDoc.Height = new SvgUnit(svgDoc.Height.Type, svgDoc.Height * scalar); return svgDoc; } /// <summary> /// Exports the chart to the specified HttpResponse object. This method /// is preferred over WriteToStream() because it handles clearing the /// output stream and setting the HTTP reponse headers. /// </summary> /// <param name="httpResponse"></param> internal void WriteToHttpResponse(HttpResponse httpResponse) { httpResponse.ClearContent(); httpResponse.ClearHeaders(); httpResponse.ContentType = this.ContentType; httpResponse.AddHeader("Content-Disposition", this.ContentDisposition); WriteToStream(httpResponse.OutputStream); } /// <summary> /// 导出 /// </summary> /// <param name="outputStream">流</param> /// <returns>文件扩展名 和 ContentType</returns> internal ExportFileInfo WriteToStream(Stream outputStream) { ExportFileInfo fi = new ExportFileInfo(); string[] fileExtenContentType = new string[2]; switch (this.ContentType) { case "image/jpeg": CreateSvgDocument().Draw().Save( outputStream, ImageFormat.Jpeg); fi.Extension = "jpg"; fi.ContentType = "image/jpeg"; break; case "image/png": // PNG output requires a seekable stream. using (MemoryStream seekableStream = new MemoryStream()) { CreateSvgDocument().Draw().Save( seekableStream, ImageFormat.Png); seekableStream.WriteTo(outputStream); } fi.Extension = "png"; fi.ContentType = "image/png"; break; case "application/pdf": SvgDocument svgDoc = CreateSvgDocument(); Bitmap bmp = svgDoc.Draw(); pdfDocument doc = new pdfDocument(this.Name, null); pdfPage page = doc.addPage(bmp.Height, bmp.Width); page.addImage(bmp, 0, 0); doc.createPDF(outputStream); fi.Extension = "pdf"; fi.ContentType = "application/pdf"; break; case "image/svg+xml": using (StreamWriter writer = new StreamWriter(outputStream)) { writer.Write(this.Svg); writer.Flush(); } fi.Extension = "svg"; fi.ContentType = "image/svg"; break; default: throw new InvalidOperationException(string.Format( "ContentType '{0}' is invalid.", this.ContentType)); } return fi; } /// <summary> /// 导出 /// </summary> /// <param name="ExportFileInfo">文件信息</param> /// <returns>图片字节数组</returns> internal byte[] WriteToBuffer(out ExportFileInfo fi) { fi = new ExportFileInfo(); byte[] buffer = null; int length = -1; // File(buffer, fileExtenContentType[1], fileName); string[] fileExtenContentType = new string[2]; switch (this.ContentType) { case "image/jpeg": using (MemoryStream seekableStream = new MemoryStream()) { Bitmap bmp = CreateSvgDocument().Draw(); bmp.Save( seekableStream, ImageFormat.Jpeg); buffer = seekableStream.GetBuffer(); } fi.Extension = "jpg"; fi.ContentType = "image/jpeg"; break; case "image/png": // PNG output requires a seekable stream. using (MemoryStream seekableStream = new MemoryStream()) { CreateSvgDocument().Draw().Save( seekableStream, ImageFormat.Png); buffer = seekableStream.GetBuffer(); } fi.Extension = "png"; fi.ContentType = "image/png"; break; case "application/pdf": using (MemoryStream seekableStream = new MemoryStream()) { SvgDocument svgDoc = CreateSvgDocument(); Bitmap bmp = svgDoc.Draw(); pdfDocument doc = new pdfDocument(this.Name, null); pdfPage page = doc.addPage(bmp.Height, bmp.Width); page.addImage(bmp, 0, 0); doc.createPDF(seekableStream); buffer = seekableStream.GetBuffer(); } fi.Extension = "pdf"; fi.ContentType = "application/pdf"; break; case "image/svg+xml": buffer = Encoding.UTF8.GetBytes(this.Svg); fi.Extension = "svg"; fi.ContentType = "image/svg"; break; default: throw new InvalidOperationException(string.Format( "ContentType '{0}' is invalid.", this.ContentType)); } return buffer; } } /* 调用示例 * 引用程序集: sharpPDF.dll,Svg.dll * //修改 HighChart 导出服务器路径 //exporting: { url: '/HighCharts/Export', filename: 'MyChart', 1200 }, [ValidateInput(false)] [HttpPost] public ActionResult Export(string filename, string type, int width,string svg) { Exporter export = new Exporter(filename, type, width, svg); //// 1、文件名输出 //FileStream fileWrite = new FileStream(@"d:HighCharts导出图片.png", FileMode.Create, FileAccess.Write); //ExportFileInfo fi = export.WriteToStream(fileWrite); //string fileName = "导出的图片." + fi.Extension; //fileWrite.Close(); //fileWrite.Dispose(); //return File(@"d:HighCharts导出图片.png", fi.ContentType, fileName); // 2、 字节输出 ExportFileInfo fi; byte[] buffer = export.WriteToBuffer(out fi); string fileName = "导出的图片." + fi.Extension; return File(buffer, fi.ContentType, fileName); } */ }
工具类和sharpPDF.dll,Svg.dll程序集下载
http://download.csdn.net/detail/qq_21533697/9467247