Accessing files on local machine in Windows 8 Metro Style Apps using JavaScript and HTML5
This article is written on pre-release version of the software and is subject to change in future release.
Here I’ll be reading a list of files from the client machine and displaying it on the page.
I created a new blank JavaScript Metro Style App project.
I’ll be using jQuery to update the content on to the file, so I’ll run the below command in the Package Manager Console.
1: Install-Package jQuery
This creates a Scripts folder in my project with the latest version of jQuery (at the time of writing).
After a little bit of modifying, this is what my html page looks like.
You can see I’ve added a reference to the jQuery API (just above the closing body tag). I have also created a program.js file where I’ll be writing all my code and a reference for the same has been added to the html page as well.
Now let’s get to the JavaScript side. The initial lines of code in my program.js look as below.
1: (function () {
2: "use strict";
3:
4: })();
The phrase, ‘use strict’ is not a Metro Style App declaration. It has been with JavaScript for quite some time. Read more about this from John Resig himself.
1: function initialize() {
2: var openpicker = new Windows.Storage.Pickers.FileOpenPicker();
3: openpicker.fileTypeFilter.replaceAll([".txt", ".rtf"]);
4: openpicker.pickMultipleFilesAsync().then(function (files) {
5: var fileNames = '';
6: files.forEach(function (file) {
7: fileNames += file.displayName + '<br/>';
8: });
9: $('#contentDiv').html(fileNames);
10: });
11: }
Here’s what the above method is doing. I create an instance of the FileOpenPicker and add a couple of file type filters to it.
Based on what the user selects, I read each of the files async and once that is done, the anonymous function passes a collection of these files. The ‘then’ part of the expression kicks in once the files are picked up (in async mode) is complete.
I’m reading the display name of each of these files to finally show them in the Div element. Well, I could’ve done the ‘display it on the page’ through good ol’ JavaScript as well, but just wanted to show how seamless both jQuery and WInJS are.
As a last step, I need to wire up this event so that it gets called when the page loads.
1: document.addEventListener("DOMContentLoaded", initialize, false);
This basically says, once the DOMContentLoaded event fires, the initialize function is called. Again, the addEventListener is a JavaScript function that Metro Style Apps are reusing – details here and here.
Time for some screenshots.
I click on the open button at the bottom and the page gets rendered as below.
This what the ‘My Documents’ folder looks like in Windows Explorer.
Here’s something interesting I want to tell you. There is a ‘file’ variable declared in the above snippet. This is not just a string variable or some custom object (I’ve not declared any such object in the project) of JavaScript creates. THIS IS THE ACTUAL FILE FROM THE FILE SYSTEM ITSELF. Here’s the proof:
Properties ‘dateCreated’, ‘displayName’, ‘fileType’ and methods ‘copy’, ‘delete’ ‘move’ (async versions of course) make that evident.
There is a second method of doing what I’ve done above. The benefit of this second method is that it reads the files directly without user having to select a list of files. But on the downside, in order to use this method, you need to add application capability to access the document library folder and provide a file type association. Read the suggestions on MSDN here and here before you implement it this way.
Below is the implementation of reading the documents library folder.
1: function initialize() {
2: Windows.Storage.KnownFolders.documentsLibrary.getFilesAsync().then(function (files) {
3: var fileNames = '';
4: files.forEach(function (file) {
5: fileNames += file.displayName + '<br/>';
6: });
7: $('#contentDiv').html(fileNames);
8: });
9: }
So I’m getting all the files in the documentsLibrary folder (which maps to the My Documents folder). The rest of the code is the same as the one used above. If I run the app without adding the capabilities, I get an error message:
The details below state: ‘Access to the specified location (DocumentsLibrary) requires a capability to be declared in the manifest’. In order to provide capability to the documents library, just select the checkbox in the package.appxmanifest file.
Running the app now gives me the error saying ‘Access to the specified location (DocumentsLibrary) requires a file type association to be declared in the application manifest’.
In order to register file type associations on behalf of the app:
When I run the app now, things work fine and I see the below getting rendered on the page.
Since I did not associate the .rtf file type in my declaration, the RichTextDocument does not get listed.
So these are the two methods I wanted to detail about in this article.
My encounters with Metro Style Apps are becoming interesting by the day!