Uploading image to the web service in WinJS application

Published November 27, 2013 1:07 pm

It is very likely that you need to have functionality to pick single or multiple image(s) and upload to your web service in your winjs windows store application. First, we will go through single image case. I have seen image pick & upload experience very often in facebook and google plus web client. Both of the web clients have ‘native’ experience for picking & uploading image(s). What I mean by native is that they have custom built experience that fits into their overall user experience. You will need to build a custom image select control that will do some or all of these:

  1. Launch picker – On click, launch windows file picker initialized to pick image file.
  2. Display preview – of the selected image. If no image is selected, display a placeholder image.
  3. Store file object – keep the file object picked by the user until it is submitted to the web service.
  4. View – you may need to show the preview of the image that already exists at the web service.
  5. delete command – context menu or other way to let user delete the uploaded image.
  6. download progress – related to (4), show progress while the image is downloading from the web service.
  7. show error – related to (4), show error if the image download fails.
  8. send command to service – to delete or upload the image
  9. show progress of command sent to the service
  10. reduce the size of the picked image before upload to the service.

The above is top down view of all the things related to uploading image in your winjs client. Building a custom control in winjs is a good topic on its own. We will not go over it in this post. This msdn blog post is a good start for building custom winjs control in your project.

Let’s get started.
html:

<img class="select-image" src="images/placeholder.png" />

js:

 
    var page = WinJS.UI.Pages.define('/pages/page1/page.html', 
    {
        ready: function onready(element, options)
        {
             ...
             var img = element.querySelector('.select-image');
             img.addEventListener('click', this.onclick.bind(this));
        }),
        onclick: function onclick()
        {
            var self = this;
            var img = this.element.querySelector('.select-image');
            this.pickSingleImage().then(function onpicksinglefile(file)
            {
                if (!file)
                    return;

                // set the blob to img.src for preview
                var imageUrl = URL.createObjectURL(file, { oneTimeOnly: true });
                img.src = imageUrl;
                // keep file object for upload later
                self.selectedFile = file;
            });
        },
        // launches file open picker initialized to pick an image
        pickSingleImage: function pickSingleImage()
        {
            // Verify that we are currently not snapped, or that we can unsnap to open the picker
            var currentState = Windows.UI.ViewManagement.ApplicationView.value;
            if (currentState === Windows.UI.ViewManagement.ApplicationViewState.snapped &&
                !Windows.UI.ViewManagement.ApplicationView.tryUnsnap())
            {
                // Fail silently if we can't unsnap
                return WinJS.Promise.timeout();
            }

            // Create the picker object and set options
            var openPicker = new Windows.Storage.Pickers.FileOpenPicker();
            openPicker.viewMode = Windows.Storage.Pickers.PickerViewMode.thumbnail;
            openPicker.suggestedStartLocation = Windows.Storage.Pickers.PickerLocationId.picturesLibrary;
            // Users expect to have a filtered view of their folders depending on the scenario.
            // show file types that are accepted by your service 
            openPicker.fileTypeFilter.replaceAll([".gif", ".jpg", ".jpeg"]);

            // Open the picker for the user to pick a file
            return openPicker.pickSingleFileAsync();
        },
        // returns a promise that completes on upload of the file to the url.
        uploadBlob: function uploadBlob(url, file)
        {
            var data = MSApp.createFileFromStorageFile(file);
            var xhrOptions = {
                type: 'put', // this may be post if your web service expects http post
                url: url,    // url for the web service
                headers: {
                    'Content-Type': 'image/jpeg',
                    'Content-Length': data.size,
                    // TODO - add any other headers that service may expect
                },
                data: data,
            };

            return WinJS.xhr(xhrOptions);
        },

The code above is more or less self explanatory. Few notes:

  1. uploadBlob needs to be invoked by other function when image is to be uploaded.
  2. For uploading image to azure blob, upload code will look similar. you can refer this post.

There we are. Current code will allow to pick, preview and upload an image file to your web service.

It does not cover all the 1-10 things listed above yet. Did your app need it?