highcharts-on-a-server
Сегодня мы поговорим об использовании highcharts.js графиков на стороне сервера. Весь код будем писать на С#, обойдемся совсем без javascript. В результате получим файл с графиком, который можно будет сохранить на диск или например приложить к письму.

Беглый поиск хороших бесплатных .net библиотек для создания графиков не увенчался успехом. Лучшей из всех найденных библиотек была ms-chart, но судя по отсутствию обновлений и хорошей документации сама Microsoft ее давно забросила.

Выбор пал на highcharts.js — очень гибкая библиотека для построения графиков, которая широко применяется на фронтенде.

Ее возможности значительно превосходят все те библиотеки которые есть для .net. Существует два варианта использования highcharts.js на сервере:

  • использовать phantom.js и обращаться к библиотеке через него
  • использовать highchart-export-module

Был выбран второй вариант, так как phantom.js не возможно запустить в Azure Web App (proof). Для работы с highchart-export-module необходимо поднять свой сервер (см. официальное руководство или вот этот блог), но если делать это лень можно использовать сервер highchart.js (http://export.highcharts.com/).

У highchart-export-module довольно простой HTTP API. Для того чтобы общаться с ним из .net была написана небольшая библиотека highcharts-export-client. Давайте рассмотрим ее поближе.

highcharts-export-client


Как и большинство .net библиотек, установим ее из NuGet.

Install-Package highcharts-export-client

Для создания графика, используем следующий код:

    var client = new HighchartsClient("http://export.highcharts.com/");

    var options = new
    {
        xAxis = new
        {
            categories = new[] { "Jan", "Feb", "Mar" }
        },
        series = new[]
        {
            new { data = new[] {29.9, 71.5, 106.4} }
        }
    };

    var res = await client.GetChartImageFromOptionsAsync(JsonConvert.SerializeObject(options));

    File.WriteAllBytes("image.png", res);

Результат работы кода, представлен на изображении ниже.

Basic chart

Данные для графика можно передавать в виде настроек highcharts. Это удобно если вы используете highcharts на фронтенде, достаточно скопировать настройки и вы получите точно такой же график на стороне сервера.

    await client.GetChartImageFromOptionsAsync(your_highcharts_settings);

Также данные можно передавать в svg формате.

    await client.GetChartImageFromSvgAsync(svg);

Качество и формат результирующего файла можно настроить передав в конструктор объект HighchartsSetting.

    var settings = new HighchartsSetting
    {
        ExportImageType = "jpg",         
        ImageWidth = 1500,
        ServerAddress = "http://export.highcharts.com/"
    };

    var client = new HighchartsClient(settings);

Поддерживаются форматы png, jpg, pdf и svg. Максимальное разрешение файла 2000px — это ограничение накладывает highchart-export-module.

Исходный код библиотеки доступен на Github — highcharts-export-client.

Спасибо за внимание!

Комментарии (9)


  1. lair
    17.03.2016 12:01
    +3

    Исходный код библиотеки доступен на Github — highcharts-export-client.

    private async Task<HttpResponseMessage> MakeRequest(Dictionary<string, string> settings)
    {
      using (var httpClient = new HttpClient())
      {
        var response =  await httpClient.PostAsync(_settings.ServerAddress, new FormUrlEncodedContent(settings));
        response.EnsureSuccessStatusCode();
        return response;
      }
    }

    (далее везде аналогично)

    1. Зачем вы создаете HttpClient на каждый вызов?
    2. Зачем вам надо, чтобы возврат после await происходил в тот же контекст, что и был вызов?


    1. sochix
      17.03.2016 12:10

      Спасибо за замечания! Согласен с вами по первому и второму пункту. Исправлю.


    1. sochix
      17.03.2016 12:30

      Добавил изменения https://github.com/sochix/highcharts-export-client/commit/f78ef4940e6ad14f7325cb5510b83b3c7f0a194b. Если есть еще замечания прошу создать issue на github.


  1. northicewind
    17.03.2016 12:18

    А в чем смысл генерировать график на сервере? Статичная картинка в качестве графика не очень удобна. Почему не отдать с сервера JSON и позволить клиенту нарисовать нормальный интерактивный график? Для веба можно использовать тот же highcharts, для мобильных платформ тоже решений хватает.


    1. sochix
      17.03.2016 12:22
      +2

      Передо мной стояла задача вставлять графики в email отчеты, а большинство email клиентов не поддерживает javascript. Так что единственный выход прикладывать статическую картинку.


    1. ese
      17.03.2016 12:25
      +3

      В статье написано. Например, приложить к письму. Мы используем создание статики для отправки графиков в слак, но делаем все на phantom.js.


      1. sochix
        17.03.2016 12:27
        -1

        А какой у вас хостинг? Мы тоже сначала хотели использовать phantom, но в Azure WebApp отключен GDI


        1. ese
          17.03.2016 12:32
          +2

          У нас свой выделенный сервер.


  1. constructor
    22.03.2016 13:21

    Не получилось установить nuget пакет (https://github.com/sochix/highcharts-export-client/issues/1)
    Есть какие особенные требования к этому пакету?