Yleistä löpinää
Jossain vaiheessa saattaa tulla tarve jaella Azure Functionsin kautta staattisia tiedostoja (esim. help-sivut). Staattiset sivut voisi tallentaa vaikkapa Azure Blobsiin ja hakea ne sieltä, mutta joissain tilanteissa on helpompi laittaa tiedostot mukaan suoraan pakettiin, jolloin Functionsin ei tarvitse tehdä ylimääräisiä verkkokutsuja tiedostojen hakemista varten.
Tapa 1: .csproj ja Embedded Resources
Ensimmäinen tapa on tuttu .NET-maailmasta. Eli binäärin kääntämisen yhteydessä voidaan sen sisään laittaa mitä tahansa tiedostoja, joihin pääsee sitten ajonaikaisesti käsiksi .NET:in Reflection-rajapinnan kautta.
Operaatio aloitetaan avaamalla Azure Functions -projektin .csproj-tiedosto halutulla tekstieditorilla, ja sitten sinne lisätään uusi ItemGroup-ryhmä, jonka sisään laitetaan sitten halutut tiedostot (*-merkkiä voi käyttää useamman tiedoston mukaanotossa) omina EmbeddedResource-elementteinään
<ItemGroup>
<EmbeddedResource Include="help.html" />
</ItemGroup>
Kyseisen tiedoston sisällön voi sitten ajonaikaisesti ladata seuraavalla komennolla
string fileContent;
var assembly = typeof(Nimiavaruus.luokka).GetTypeInfo().Assembly;
using (Stream stream = assembly.GetManifestResourceStream("csprojin_nimi.help.html"))
{
using (var reader = new StreamReader(stream))
{
fileContent = await reader.ReadToEndAsync();
}
}
Jos resurssien nimet ovat hukassa, voi ne listata seuraavalla komennolla
Console.WriteLine(string.Join(',', assembly.GetManifestResourceNames()));
Tapa 2: .csproj ja FunctionAppDirectory
Toinen tapa on hieman samanlainen kuin ensimmäinen. Tälläkin kertaa projektin .csproj-tiedostoon lisätään ne tiedostot, jotka halutaan mukaan, mutta EmbeddedResourcen sijaan käytetään None-tyyppiä (joille pitäisi oletuksena olla jo oma ItemGroup, jossa on mm. host.json-tiedosto), jolloin tiedosto päätyy binääreiden kanssa samaan hakemistoon omana tiedostonaan.
<None Update="help.html">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
Ajonaikaisesti tiedoston voi sitten ladata ExecutionContextin FunctionAppDirectory-muuttujan avulla
public static async Task<IActionResult> Run([HttpTrigger(AuthorizationLevel.Function, "get", Route = null)]HttpRequest req, ILogger log, ExecutionContext context)
{
log.LogInformation("C# HTTP trigger function processed a request.");
byte[] fileContent = await File.ReadAllBytesAsync(Path.Combine(context.FunctionAppDirectory, "help.html"));
return new FileContentResult(fileContent, "text/html");
}
☁️