Reading WinRT Component Embedded Resource File in Javascript Windows Store Apps

A WinRT component can be used to include some common code along with embedded resources that can be reused in a Windows Store app irrespective of the language in which it is developed, like C#, JavaScript etc.

In this article, I explain how to read a WinRT component embedded resource file from a JavaScript Windows Store app. 

This article consists of the following 3 parts:

  1. Reading a Text file.
  2. Reading a Binary file.
  3. Reading an Image as Base64 encoded string.

Part 1:  Reading a text File

Create a WinRT component

  1. Create a new Windows Store apps class library or WinRT component say with the name "ExampleLib".

    fig1.png
     
  2. If it is a class library then open its properties and change the output to WinRT component.

    fig2.png
     
  3. Add a text file named say "Data.txt" in the project root folder with some text and change to embedded resource from its properties.

    fig3.png
     
  4. Add a new C# code file ResHelper.cs in the project root folder and add the following code in that.

using System;
using System.IO;
using System.Reflection;
using System.Threading.Tasks;
using Windows.Foundation;
 
namespace ExampleLib
{
    public sealed class ResHelper
    {
        static async Task<string> ReadResourceAsync(Assembly assembly, string resource)
        {
            string xml;
            using (var stream = assembly.GetManifestResourceStream(resource))
            {
                using (var reader = new StreamReader(stream))
                {
                    xml =
await reader.ReadToEndAsync();
                }
            }
            return xml;
        }

        public static IAsyncOperation<string> GetFileText(string fileName)
        {
            return (ReadResourceAsync(typeof(ResHelper).GetTypeInfo().Assembly, fileName)).AsAsyncOperation<string>();
        }
    }   
}

Create a Windows Store app in JavaScript

Use the following to create a Windows Store app in JavaScript:

  1. Create a new Windows Store app under language JavaScript (blank app is fine) say with name "ExampleApp"
  2. Add a reference to ExampleLib
  3. Open Js/default.js and add the following code after line args.setPromise in the activated handler.

 

var textFile = "ExampleLib.Data.txt";
ExampleLib.ResHelper.getFileText(textFile)
.done(function (result) {
//Image file success
var div = document.createElement("div");
document.body.appendChild(div);
div.textContent = result;
}, function (err) {
//Image Error 
var errDiv = document.createElement("div");
document.body.appendChild(errDiv);
errDiv.textContent = err;
});
 

The complete solution looks like as below:

fig4.png


All done, deploy and run the app, now you'll see the embedded resource content as your main page content. Try with an invalid file name; you'll see an error message.

Part 2: Reading a binary file

Part 1 explains how to read a Winrt component embedded text file. The ResHelper example method GetFileText always returns a string irrespective of the file type. This will not work for binary and image files since they must be managed as bytes. In this part, I'll explain how to send a byte array back to the JavaScript app. 

Modify WinRT component ExampleLib

     1. Add any binary file ( I've added an image file StoreLogo.png).

     2. Change to Embedded Resource from its properties  

     3. Add the following extra methods in the ResHelper class to return bytes instead of a string. 

 

/// <summary>
/// Reads a resource from assembly
/// </summary>
/// <param name="assembly">Assembly in which the resource is located</param>
/// <param name="resource">Resource name to read</param>
/// <returns>File content as byte array</returns>
 
 static async Task<IList<byte>> ReadResourceBytesAsync(Assembly assembly, string resource)
{
using (var stream = assembly.GetManifestResourceStream(resource))
{
var buffer = new byte[16 * 1024];
using (var ms = new MemoryStream())
{
int read;
while ((read = await stream.ReadAsync(buffer, 0, buffer.Length)) > 0)
{
await ms.WriteAsync(buffer, 0, read);
}
return ms.ToArray();
}
}
}
 /// <summary>
/// Gets file content as a byte array
/// </summary>
/// <param name="fileName">File resource to read</param>
/// <returns>File content as bytes</returns>
public static IAsyncOperation<IList<byte>> GetFileBytes(string fileName)
{
return (ReadResourceBytesAsync(typeof(ResHelper).GetTypeInfo().Assembly, fileName)).AsAsyncOperation<IList<byte>>();
}

Modify Windows Store JavaScript app ExampleApp

 1. Add the following extra code at the end inside the activated handler in the Js/default.js file

 

    
var binaryFile = "ExampleLib.StoreLogo.png";
ExampleLib.ResHelper.getFileBytes(binaryFile)
.done(function (result) {
 //Async call success  //the result will be of IVector type, convert it to JS array
var intArray = new Array();
for (var i = 0; i < result.length; i++)
intArray.push(result[i]);
 //get store app current application data
var applicationData = Windows.Storage.ApplicationData.current;
var localStorePath = applicationData.localFolder.path;
 //create a text area to display local folder path
var textPath = document.createElement("textarea");
textPath.setAttribute("style", "width:400px;height:50px;");
textPath.textContent = localStorePath;
document.body.appendChild(textPath);
 //save the bytes in a file with same file name
applicationData.localFolder.createFileAsync(binaryFile,
Windows.Storage.CreationCollisionOption.replaceExisting).then(function (file) {
var sampleFile = file;
return Windows.Storage.FileIO.writeBytesAsync(sampleFile, intArray);
});
                }, function (err) {
//Error 
var errDiv = document.createElement("div");
document.body.appendChild(errDiv);
errDiv.textContent = err;
});

Deploy and run the app, it'll read StoreLogo.png from the WinRT component and save it in the store app's local folder. The local folder path will be displayed in the textarea. Copy the path and open Windows Explorer, verify the new image. 

Part 3: Reading an Image as Base64 encoded string

In this part, I'll explain how to read a base64 encoded string of a WinRT component image resource and display it in the page on the fly. 
 

1. Modify WinRT component project ExampleLib

    1. Add the following extra 2 methods in ResHelper.cs that converts a byte array to a Base64 encoded string. 

 

        /// <summary>
/// Reads a resource from assembly
/// </summary>
/// <param name="assembly">Assembly in which the resource is located</param>
/// <param name="resource">Resource name to read</param>
/// <returns>File content as base 64 encoded string</returns> 
static async Task<string> ReadBase64StringAsync(Assembly assembly, string resource)
{
using (var stream = assembly.GetManifestResourceStream(resource))
{
var buffer = new byte[16 * 1024];
using (var ms = new MemoryStream())
{
int read;
while ((read = await stream.ReadAsync(buffer, 0, buffer.Length)) > 0)
{
await ms.WriteAsync(buffer, 0, read);
}
return System.Convert.ToBase64String(ms.ToArray());
}
}
}
 /// <summary>
/// Gets file content as base64 encoded string
/// </summary>
/// <param name="fileName">File resource to read</param>
/// <returns>Base64 encoded string</returns>
 public static IAsyncOperation<string> GetImage(string fileName)
{
return (ReadBase64StringAsync(typeof(ResHelper).GetTypeInfo().Assembly, fileName)).AsAsyncOperation<string>();
}

2.  Modify Windows Store JavaScript project ExampleApp

       1. Add the following code at the end inside the activated handler in the Js/default.js file.
       

   var imageFile = "ExampleLib.StoreLogo.png";
ExampleLib.ResHelper.getImage(imageFile)
.done(function (result) {
//Image file success
var img = document.createElement("img");
document.body.appendChild(img);
img.src="data:image/png;base64," + result;
}, function (err) {
//Image Error 
var errDiv = document.createElement("div");
document.body.appendChild(errDiv);
errDiv.textContent = err;
});

Deploy and run the app, you'll see the StoreLogo.png image rendered on the fly in the main page. 

Example solution attached.


Similar Articles