मैं अपने ASP.NET ऐप में System.Web.UI.DataVisualization.Charting 4.0 का उपयोग कर रहा हूं। यह इस प्रकार कुछ वातावरण में ठीक काम करता है:

var chart = new Chart();

// Define the chart area
Grid grid = new Grid();
ChartArea chartArea = new ChartArea();
[... setting lots of chartArea properties here...]

ChartArea3DStyle areaStyle = new ChartArea3DStyle(chartArea);
chart.ChartAreas.Add(chartArea);
[... more ...]

[... build Series, Legends, etc here ...]

chart.SaveImage("c:\fakepath\myreport.png", ChartImageFormat.Png);

मैंने चार्ट बनाने के लिए 95% कोड छोड़ा है (बहुत जटिल तर्क, जटिल डेटा संरचनाओं के माध्यम से बहुत सारे लूपिंग), जिसे तब डिस्क में सहेजा जाता है, और इस तरह एएसपीएक्स पेज से प्रस्तुत किया जाता है:

<img src="http://fakeserver/fakepath/myreport.png">

कुछ ग्राहक परिवेशों में यह दृष्टिकोण काम नहीं करेगा क्योंकि IIS प्रक्रिया को स्थानीय डिस्क पर लिखने की अनुमति नहीं है, और वे इसे खोलना नहीं चाहते हैं। इसके अतिरिक्त, जब एक से अधिक उपयोगकर्ता चार्ट देख रहे हों (और उत्पन्न कर रहे हों) तो यह बहुत मापनीय नहीं है, जो प्रत्येक उपयोगकर्ता के लिए अलग होगा।

मैं इस चार्ट को पूरी तरह से मेमोरी में कैसे जेनरेट कर सकता हूं?

मैं देख रहा हूँ ChartHttpHandler वर्ग, लेकिन प्रासंगिक कोड नमूने नहीं ढूंढ सकता। क्या आदर्श होगा यदि मैं ऊपर दिखाए गए चार्ट को ठीक से बना सकता हूं, लेकिन डिस्क पर सहेजने के बजाय, मैं चार्ट को इन-मेमोरी (कैश? सत्र?) में इस तरह से स्टोर कर सकता हूं कि मैं अपना <कोड> इंगित कर सकूं img> aspx पृष्ठ में उस स्मृति डेटा को टैग करें और छवि पृष्ठ पर रेंडर हो जाएगी। मैं घोषणात्मक एएसपीएक्स चार्ट निर्माण का सहारा नहीं लेना चाहता क्योंकि तर्क बहुत जटिल है और सभी को सी # कोड में करने की आवश्यकता है। मैं किसी भी दृष्टिकोण का उपयोग नहीं कर सकता जिसमें चार्ट छवि डिस्क पर लिखी जाती है।

यह कैसे किया जाता है?

0
HerrimanCoder 1 अगस्त 2018, 02:23

2 जवाब

सबसे बढ़िया उत्तर

मैंने अन्य उपयोगकर्ताओं के लिए चार्ट बनाने सहित एक संपूर्ण उदाहरण बनाया है। लेकिन मूल रूप से आप चार्ट छवि को फ़ाइल के बजाय स्ट्रीम में सहेजते हैं।

using (MemoryStream stream = new MemoryStream())
{
    chart.SaveImage(stream, ChartImageFormat.Png);
}

मैंने ब्राउज़र में छवियों को प्रदर्शित करने के लिए जेनेरिक हैंडलर बनाया है। लेकिन एक बार जब छवि एक स्ट्रीम में होती है तो आप बहुत कुछ कर सकते हैं, जैसे इसे पीडीएफ या ईमेल संदेश में डालना।

using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Web;
using System.Web.UI.DataVisualization.Charting;
using System.Web.UI.WebControls;

namespace YourNameSpace
{
    public class Handler1 : IHttpHandler
    {    
        public void ProcessRequest(HttpContext context)
        {
            //needed to generate random numbers
            Random rnd = new Random();

            //select 12 random numbers between 1 and 50 for column chart
            int[] yRange1 = Enumerable.Range(1, 50).OrderBy(i => rnd.Next()).Take(12).ToArray();

            //select 12 random numbers between 1 and 25 for line chart
            int[] yRange2 = Enumerable.Range(0, 25).OrderBy(i => rnd.Next()).Take(12).ToArray();

            //select all the month names for the labels
            string[] xLabels = Enumerable.Range(1, 12).Select(i => DateTimeFormatInfo.CurrentInfo.GetMonthName(i)).ToArray();

            //create the chart
            Chart chart = new Chart();

            //add the bar chart series
            Series series = new Series("ChartBar");
            series.ChartType = SeriesChartType.Column;
            chart.Series.Add(series);

            //add the line chart series
            Series series2 = new Series("ChartLine");
            series2.ChartType = SeriesChartType.Line;
            series2.Color = System.Drawing.Color.Purple;
            series2.BorderWidth = 2;
            chart.Series.Add(series2);

            //define the chart area
            ChartArea chartArea = new ChartArea();
            Axis yAxis = new Axis(chartArea, AxisName.Y);
            Axis xAxis = new Axis(chartArea, AxisName.X);

            //add the data and define color
            chart.Series["ChartBar"].Points.DataBindXY(xLabels, yRange1);
            chart.Series["ChartLine"].Points.DataBindXY(xLabels, yRange2);
            chart.Series["ChartBar"].Color = System.Drawing.Color.Green;

            chart.ChartAreas.Add(chartArea);

            //set the dimensions of the chart
            chart.Width = new Unit(600, UnitType.Pixel);
            chart.Height = new Unit(400, UnitType.Pixel);

            //create an empty byte array
            byte[] bin = new byte[0];

            //save the chart to the stream instead of a file
            using (MemoryStream stream = new MemoryStream())
            {
                chart.SaveImage(stream, ChartImageFormat.Png);

                //write the stream to a byte array
                bin = stream.ToArray();
            }

            //send the result to the browser
            context.Response.ContentType = "image/png";
            context.Response.AddHeader("content-length", bin.Length.ToString());
            context.Response.AddHeader("content-disposition", "attachment; filename=\"chart.png\"");
            context.Response.OutputStream.Write(bin, 0, bin.Length);
        }


        public bool IsReusable
        {
            get
            {
                return false;
            }
        }
    }
}

ब्राउज़र में छवि प्रदर्शित करने के लिए बस img एलिमेंट के src को हैंडलर की ओर इंगित करें।

<img src="Handler1.ashx" width="600" height="400" />
3
VDWWD 11 अगस्त 2018, 19:12

एक विकल्प यह है कि अपने इमेज टैग (src=data:image/base64 के माध्यम से) पर बेस64 एन्कोडेड स्रोत का उपयोग करके चार्ट को सीधे HTML में एम्बेड करें; वेब सर्वर से छवियों को प्राप्त करने के लिए किसी और http अनुरोध की आवश्यकता नहीं होने का भी इसका लाभ है।

जैसे

<img src='data:image/png;base64,src='data:image/png;base64,[base64data==]'>

ऐसा करने के लिए कई चीजों की आवश्यकता होती है।

छवि डेटा को क्रिया परिणाम के रूप में प्राप्त करने के लिए एक नियंत्रक:

   public ActionResult SomeChart(SomeViewModel model, int width, int height)
    {
        model.ChartKey = "SomeChart";
        return Content(getChartImage(() => CreateSomeChart(model, width, height), model, width, height));
    }

यह निम्नानुसार चार्ट बनाने के लिए एक विधि का उपयोग करता है:

  private Chart CreateSomeChart(SomeViewModel vm, int width, int height)
  {
      int Id = vm.Id;
      System.Web.UI.DataVisualization.Charting.Chart Chart1 = new System.Web.UI.DataVisualization.Charting.Chart();
      // usual code to draw a chart here...
      return Chart1;
  }

चार्ट प्राप्त करने के लिए अपने रेजर व्यू में कोड; मेरे विचार मॉडल में मेरे पास चार्ट की एक सूची है जो नियंत्रक में केवल क्रिया परिणाम विधियां हैं जिन्हें प्रस्तुत किया जाना है। एचटीएमएल ब्राउज़र पर भेजे जाने से पहले रेंडर एक्शन का उपयोग होगा और परिणामस्वरूप चार्ट को बेस 64 एन्कोडेड तरीके से रेखांकित किया जाएगा।

यह public ActionResult SomeChart नियंत्रक है जिसे Html.RenderAction विधि द्वारा बुलाया जाना चाहिए, और इस उदाहरण के लिए Model.ChartList[] = {"SomeChart"}

if (Model.ChartList.Count() > 1)
{
        xs = 450;
        ys = 300;
}

foreach(var chart in Model.ChartList)
{ 
    Html.RenderAction(chart, "SomeController", new { model = Model, width = xs, height = ys });
}

अंतिम बिट जो इसे एक साथ जोड़ता है वह getChartImage विधि है।

  private string getChartImage(Func<Chart> getChart, object routevals, int width, int height, string chartKey="")
    {
        string name = "Chart";
        if (routevals is SomeViewModel)
        {
            var cvm = routevals as SomeViewModel;
            chartKey = cvm.ChartKey;
            name = cvm.ChartKey;
        }

        using (var stream = new MemoryStream())
        {
            var Chart1 = getChart();
            Chart1.ImageType = ChartImageType.Png;
            Chart1.Palette = ChartColorPalette.BrightPastel;
            Chart1.SuppressExceptions = true;

            // Set chart custom palette
            Chart1.Palette = ChartColorPalette.None;
            Chart1.PaletteCustomColors = Dashboard.Support.ChartPalettes.ColorsBigList;

            Chart1.Width = width;
            Chart1.Height = height;
            Chart1.RenderType = RenderType.ImageTag;

            Chart1.BackColor = Color.White;

            Chart1.BackImageAlignment = ChartImageAlignmentStyle.BottomLeft;
            Chart1.BorderSkin.SkinStyle = BorderSkinStyle.None;
            Chart1.BorderSkin.BorderWidth = 0;
            //Chart1.BackImageTransparentColor
            Chart1.BorderColor = System.Drawing.Color.FromArgb(26, 59, 105);
            Chart1.BorderlineDashStyle = ChartDashStyle.Solid;
            Chart1.BorderWidth = 0;

            Chart1.SaveImage(stream, ChartImageFormat.Png);
            string encoded = Convert.ToBase64String(stream.ToArray());

            if (Request != null && Request.Browser != null && Request.Browser.Browser == "IE" && Request.Browser.MajorVersion <= 8)
            {
                /*
                 * IE8 can only handle 32k of data inline so do it via the cached getChart
                 * method - i.e. store the chart in the cache and return a normal image.
                 */
                if (encoded.Length > 32000)
                {
                    StringBuilder result = new StringBuilder();
                    if (string.IsNullOrEmpty(chartKey))
                        chartKey = String.Format("{0}{1}", name, Guid.NewGuid());

                    System.Web.Helpers.WebCache.Set(chartKey, stream.ToArray());

                    result.Append(String.Format("<img width='{0}' height='{1}' src='{3}' alt='' usemap='#ImageMap{2}'>", width, height, name,
                        Url.Action("getChart", new { key = chartKey })));

                    return result.ToString() + Chart1.GetHtmlImageMap("ImageMap" + name); ;
                }
            }
            /*
             * render using data inline for speed
             */
            string img = String.Format("<img width='{0}' height='{1}' src='data:image/png;base64,{{0}}' alt='' usemap='#ImageMap{2}'>", Chart1.Width, Chart1.Height, name);
            return String.Format(img, encoded) + Chart1.GetHtmlImageMap("ImageMap" + name);
        }
    }
0
Richard Harrison 8 अगस्त 2018, 19:03