Поток HEIC картинок загружается в OneDrive. Для передачи их далее в другую систему понадобилось конвертировать их в JPG.
Из коробки Power Automate кстати тоже может это делать(«Convert File» + «Create File»), но файл не должен быть больше 2Mb..
Вариант который обрабатывает любые файлы:
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')
p.p.s.: Также подобный подход можно использовать например чтобы вытаскивать картинки из форм infopath, правда функция само собой будет другая (картинки в SharePoint Infopath лежат в строке, где первые байты занимает название файла).