0

I have an azure function that has a Queue trigger. In the trigger I create a pdf. This pdf should contain a couple of images. How do I include these images in an azure function so that they can be accessed from the code?

My previous version of the code was implemented as a webjob and here we accessed the image like this:

var path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Images", "My_Image.png"

This does not seem to work in my azure function as this path no longer contains my image. The image has build action "None" and is set to "Copy always".

Would be great if someone could point me in the right direction.

Fred
  • 187
  • 5
  • 23

2 Answers2

3

There are a number of ways forward here:

  • You could use Blob Storage to contain your image. You can open that programmatically and get a stream, url, etc.
  • It might be possible to proceed with your current plan although it seems a little more fraught than I would expect: Including a file when I publish my Azure function in Visual Studio
  • You could possibly convert the image to base64 and include it in code.
Brian MacKay
  • 31,133
  • 17
  • 86
  • 125
1

There is a much easier way depending on your CI/CD pipeline to not have to put few files into a separate blob container. In my case, I just needed to include ONE font (ttf) file as my azure function was generating a pdf.

Note: DI will make things easier if you choose to follow this method.

Create a folder called 'Resources' (not necessary but keeps the project clean), and add your file in it. Right-click properties and select 'Copy if Newer'.

Next if you're using the Azure DevOps, add this to your .csproj -

  <Target Name="CopyRequiredResources" AfterTargets="_FunctionsPostPublish">
    <ItemGroup>
      <ResourcesToCopy Include="$(ProjectDir)Resources\*.*" />
    </ItemGroup>
    <Copy SourceFiles="@(ResourcesToCopy)" DestinationFolder="$(PublishDir)bin" />
  </Target>

If you're publishing directly from Visual Studio, then change DestinationFolder to "$(TargetDir)bin".

Edit: Above mentioned destination folders, could be the other way around. It's been a while. Try out both. Best way is to publish to ZIP files and check if the bin folder has the required files. In the case of DevOps, check the bin of the created artifacts. And make the necessary changes to the DestinationFolder.

Basically moving all the required files to the bin folder to keep things easy. The above will work for Azure Function, now to also make sure that the files exists in the same path for local development as well, add the following -

  <Target Name="PostBuild" AfterTargets="PostBuildEvent">
    <ItemGroup>
      <ResourcesToCopy Include="$(ProjectDir)Resources\*.*" />
    </ItemGroup>
    <Copy SourceFiles="@(ResourcesToCopy)" DestinationFolder="$(TargetDir)bin" />
  </Target>

In the above bits of MSBuild actions, you're moving your required resources to the publish/bin folder.

now in my pdf writer i had to inject the execution context to get the running app directory -

public class PdfWriter
{
   string resourceLoc;

   public PdfWriter(IOptions<ExecutionContextOptions> contextOptions)
   {
      resourceLoc = Path.Combine(contextOptions.Value.AppDirectory, "bin");
   }

   // img would be in Path.Combine(resourceLoc, "img.jpg");
}

Why I like this method better than the rest -

  1. Dont require a separate blob container just for 1-2 files.
  2. If you decide to change the img or your resource, you dont need to re-do the Base64 conversions. You just replace and republish.
  3. Its all contained within the app itself and has no outside dependency (this ties back to point 1), and hence if you decide to revisit the code in the future, it'll run out of the box.
  4. Makes things easy for collaboration etc. As your team is not reliant on keeping their local blob storage with the required files for things to work.
  5. Further to point 4, I would use this method even if I had several resources. Function code is anyways kept in Azure Storage, so might as well ensure your resources are kept with your code neatly packaged.
Bandook
  • 658
  • 6
  • 21