Записи с меткой «Azure»

Поток HEIC картинок загружается в OneDrive. Для передачи их далее в другую систему понадобилось конвертировать их в JPG.

Из коробки Power Automate кстати тоже может это делать(«Convert File» + «Create File»), но файл не должен быть больше 2Mb..

Вариант который обрабатывает любые файлы:

1-1-2023-07-26_174225

1) «Get file content» в Power Automate уже возвращает результат в base64, поэтому нам не нужно ничего ковертировать. единственное что..
2) его результат содержит не только содержимое файла, но и его имя и тип. Так чтобы добраться именно до самого содержимого] — нужно использовать такую строку:

body('Get_file_content')['$content']

Тогда мы получим сам код картинки, который и будем конвертировать.

3) При создании Azure функции ей будет присвоен адрес и код. он добавляется к адресу в поле URI и по нему происходит авторизация(там где “?code=fFyK..”) . В «Body» отсылается ID, имя файла и полученный выше контент в base64.

Со стороны Azure функция может выглядеть к примеру так:

using System;
using System.IO;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using ImageMagick;

namespace HeicToJpgWebservice
{
    public static class Function1
    {
        [FunctionName("HeicToJpgWebservice")]
        public static async Task<IActionResult> Run(
            [HttpTrigger(AuthorizationLevel.Function, "post", Route = null)] HttpRequest req,  ILogger log)
        {
            log.LogInformation("C# HTTP trigger function processed a request.");

            // Get request body
            string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
            dynamic data = JsonConvert.DeserializeObject(requestBody);

            string base64String = data?.content;
            string id = data?.id;
            string name = data?.name;

            log.LogInformation($"Processing {id}, filename is: {name}");

            byte[] heicAsByteArray = null;
            string jpgAsBase64 = string.Empty, responseMessage = string.Empty;

            try
            {
                heicAsByteArray = Convert.FromBase64String(base64String);

                using (MagickImage image = new MagickImage(heicAsByteArray))
                {
                    // convert
                    image.Format = MagickFormat.Jpeg;

                    // return result Jpg as base64
                    jpgAsBase64 = image.ToBase64();

                    responseMessage = string.IsNullOrEmpty(jpgAsBase64) ? $"Error during conversion: id = {id}, name = {name}" : jpgAsBase64;
                }
            }
            catch (Exception ex)
            {
                log.LogWarning($"Error during conversion: id = {id}, name = {name}, exception: {ex?.InnerException?.Message}");
                return new BadRequestObjectResult($"Error during conversion: id = {id}, name = {name}, exception: {ex?.InnerException?.InnerException}, {ex?.InnerException?.Message}");
            }

            return new OkObjectResult(responseMessage);
        }
    }
}

Собственно id и имя файла особо не нужны, они передаются на всякий случай чтобы отловить потенциальную ошибку в конвертации. Функция получает содержимое HEIC файла в base64, конвертирует через библиотеку Magick.NET-Q16-AnyCPU (ставится через Nuget), и возвращает обратно тоже base64, но уже формата JPEG.

После HTTP вызова функции выполняется правый блок (“Scope create file” внизу):

В развёрнутом виде:

Со стороны Power Automate остаётся этот base64 подхватить и создать на его основе файл в другой папке, на этот раз с расширением *.jpg. Сконвертированное значение лежит в «body(‘HTTP’)», цифра 1 выше.

Правда чтобы создать файл — в «File Content» нужно отдать это значение в binary (цифра 2 на рисунке выше):

base64ToBinary(outputs('Compose_result_from_Azure_function'))

p.s.: Для того чтобы флов срабатывал только для *.heic файлов — в самом первом шаге можно использовать trigger condition:

@endswith(tolower(triggerOutputs()?['body/{FilenameWithExtension}']), '.heic')

  8-1-2023-07-26_173737

8-2-2023-07-26_173803

p.p.s.: Также подобный подход можно использовать например чтобы вытаскивать картинки из форм infopath, правда функция само собой будет другая (картинки в SharePoint Infopath лежат в строке, где первые байты занимает название файла).