Page 52 - MSDN Magazine, April 2017
P. 52
includes the rendering capability (mostly presentation through HTML) and Standard script execution.
What you’re working with now is an app. In the apps world, for developers, the file download should be explicitly coded for— otherwise, the remote file is just a URL and it’s unclear what the app/container would do with a remote file URL (I can discuss what might be happening under the hood through specialized debugging tools, however, I won’t go into that for now).
To handle these kinds of scenarios, you need to invoke the appropriate UWP APIs. These APIs can co-exist with the code that makes those functionalities work when running the Web site us- ing a browser. Figure 2 shows the code involved.
You can write the code in Figure 2 on the button click or wher- ever the file download functionality is expected. The code snippet
Figure 3 File Download JavaScript Code (Smaller Files)
uses the BackgroundDownloader class (bit.ly/2jQeuBw), which has lots of benefits, such as persisting downloads in background post- app suspension and the ability to download large files.
The code in Figure 2 actually creates the same experience as a browser would, such as prompting the user to select a file location (fileSavePicker variable), initiating the download (downloader variable) and writing it to the selected location.
Alternatively, you can use the code in Figure 3 for smaller file downloads, which will run as long as the app is running:
The code in Figure 3 uses the Windows.Web.Http.HttpClient to handle the file download operation (bit.ly/2k5iX2E). If you compare the code snippets in Figure 2 and Figure 3, you’ll notice that the latter requires a bit of advanced coding, which gives you more con- trol over the file download. This way, you’re also able to explore the multiple ways to save a stream to a file using a UWP app.
Also, in the case where the app also processes the files that were downloaded, it’s best to use the FutureAccessList property to cache and access the location where the file was saved (bit.ly/2k5fXn6). This is important because the user can choose to save the downloaded files anywhere on the system (such as in D:\\\\\\\\files\\\\\\\\ or in C:\users\\\\\\\\ myuser\\\\\\\\myfiles\\\\\\\\) and the app container, being a sandbox process, might not be able to directly access the file system without user- initiated actions. This class can be useful to avoid extra steps for the user to open the same file again. To use this class, it’s required to open the file using the FileOpenPicker at least once.
This should help streamline file download functionality in the hosted Web apps and deliver an intuitive UX. (Tip: Make sure to add the file URL domain to the ApplicationContentURI at bit.ly/2jsN1WS to avoid runtime exceptions.)
Session Management
It’s common for most modern apps today to persist data between users’ multiple sessions. As an example, imagine having to log into a frequently used app every time the app is launched. It would be time-consuming if the app is launched multiple times in a day. There are classes within the Windows Runtime framework available to the Web apps, which are converted to UWP apps.
Figure 4 Cortana Commands XML
// Use the Windows.Web.Http.HttpClient to download smaller files and // files are needed to download when the app is running in foreground.
(function() {
if (typeof Windows !== 'undefined' &&
typeof Windows.UI !== 'undefined' &&
typeof Windows.ApplicationModel !== 'undefined') {
function WinAppSaveFileWinHTTP() {
var uri = new Windows.Foundation.Uri("<URL of the file being downloaded>");
var fileSavePicker = new Windows.Storage.Pickers.FileSavePicker(); fileSavePicker.fileTypeChoices.insert("EXT file",
[".ext"]); //insert appropriate file format through code. fileSavePicker.defaultFileExtension = ".ext";
// Extension of the file being saved. fileSavePicker.suggestedFileName = "file.ext";
// Name of the file to be downloaded. Needs to be replaced programmatically. fileSavePicker.settingsIdentifier = "fileSavePicker1";
fileSavePicker.pickSaveFileAsync().then(function (fileToSave) {
console.log(fileToSave);
var httpClient = new Windows.Web.Http.HttpClient();
httpClient.getAsync(uri).then(function (remoteFile) {
remoteFile.content.readAsInputStreamAsync().then( function (stream) {
fileToSave.openAsync( Windows.Storage.FileAccessMode.readWrite).then( function (outputStream) {
Windows.Storage.Streams.RandomAccessStream.copyAndCloseAsync( stream, outputStream).then(function (progress, progress2) {
// Monitor file download progress. console.log(progress);
var temp = progress2;
}); });
}); });
});
} }
})();
<?xml version="1.0" encoding="utf-8"?>
<VoiceCommands xmlns="http://schemas.microsoft.com/voicecommands/1.1">
<CommandSet xml:lang="en-us" Name="AdventureWorksCommandSet_en-us"> <CommandPrefix> Adventure Works, </CommandPrefix>
<Example> Show trip to London </Example>
<Command Name="showTripToDestination"> <Example> Show trip to London </Example> <ListenFor RequireAppName=
"BeforeOrAfterPhrase"> show trip to {destination} </ListenFor> <Feedback> Showing trip to {destination} </Feedback> <Navigate/>
</Command>
<PhraseList Label="destination"> <Item> London </Item>
<Item> Dallas </Item>
</PhraseList>
</CommandSet>
<!-- Other CommandSets for other languages --> </VoiceCommands>
38 msdn magazine
UWP Apps