The goal for today is to explain the motivation for the latest CC feature added by Henrique Graca @hjgraca out of Portugal, and show how to enable it.

Henrique is one of our Cloud Solution Architects and got a complaint from one of our customers with respect to the loss of quality when uploading and using images with Company Communicator.

The image quality loss issue

The loss of quality was being caused by the way we used the React Image File Resizer library in the code that manages the authors interface.

That library was being used to do basically two things:

  1. Convert the image selected into JPEG and with a accepted loss in quality of 20%.
  2. Resize the image to 400 x 400 pixels so we can easily fit it inside the adaptive card used for the communication.

The quality problem was actually caused by the combination of the two processes. The JPEG conversion with the accepted loss causes an obvious loss in the quality, but when combined with the resizing process turns it into an even worse problem.

The real motivation behind the approach used originally was to ensure we have a relatively small footprint for the image and thus impacting less into the overall limitation we have for the whole card, which is 32 Kb.


Henrique changed the CC code to upload the image to the blob service that is available on the same Azure storage subscription used to store the Company Communicator tables.

How it works

Going into more technical details, after a draft is saved (edits included) CC calls the backend with a Base64 encoded string that represents the image we added from our local disk.

In the backend we convert that base64 string into a byte array, then we securely connect to the Azure Blob Storage and upload that byte array into a container called imageupload in the same storage account that you are already using for CC. The new images are stored with a new Guid, so they are harder to guess and prevent naming conflicts.

It is important to build names for the images that are hard to guess, that is because images in CC need to be public for Teams to download them and show. The way we ensure security is with the randomness of the name (Guid) and by generating a SAS token for that specific Blob (Image), the SAS token expiration is configured with a new property ImageUploadBlobStorageSasDurationHours that is also available in the Azure App Service Settings.

Once the token expires, no one would be able to access that image anymore. Then make sure you setup a expiration date in the App Settings with an appropriate value, so you ensure all users will have enough time to actually see the images.

The new method was added to the DraftNotificationsController class, you can check the source code here.

How to use the feature

The use of the blob storage was made completely optional and customers that still want to use the original approach, storing images in the database table don’t need to change anything when syncing to the latest version of our community fork.

For those ones that want to upload images to the blob storage, a new configuration variable needs to be included on the App Service.

Note: First you need to ensure you are using the latest version of the Company Communicator community fork. To update you need to logon to the Azure administrative portal with admin credentials and resync the deployment for the App Service and all Azure functions. You can do that clicking on each one of the resources, going to the Deployment Center and clicking Sync.

The following items document the steps that need to be taken:

  1. Open the Azure administration portal with the appropriate rights.
  2. Go to the Resource Group hosting Company Communicator resources and find the App Service being used.
  3. Double click the App Service and select Configuration (under Settings) on the left panel.
  4. Click “+ New application setting” and create a new configuration with the following:
    • Name: ImageUploadBlobStorage
    • Value: true
  5. Leave the “Deployment slot setting” unchecked and click OK.
  6. Click Save.

Done. Your Company Communicator deployment is enabled to upload to and use images from the Azure blob storage automatically.

Note: Remember you also have the ImageUploadBlobStorageSasDurationHours that controls the duration of the image token. If not set, that variable has a default value of one week (168 hours).

Additional image quality improvements

When the new feature is enabled, we are not resizing neither converting images to JPEG anymore. The upload interface is restricting the files to image files, so any image format will be used by the system as source for the communications image.

The adaptive card used by CC already present the image in a 400×400 size, but this time is just a presentation resize and not something done to the file before uploading it. In that case the quality is a lot better, and doesn’t affect much the size of the card.

We hope you enjoy the new feature. That one was a request for multiple customer and finally Henrique took the time to support the community and contribute. Thanks Henrique!

Disclaimer – The information contained in this blog post doesn’t represent the official Microsoft guidance or best practices. It is just the view of the author on current alternatives, implementations and workarounds for common issues and/or business needs. Please refer to official Microsoft documentation and evaluate carefully any steps, code or procedures documented herein. The author doesn’t offer any warranty. Use this information at your own risk.