Plupload: previewing images and getting Data URI

I am working on a project where users can be created and assigned an image. The natural choice to upload images is to use Plupload. Plupload is a well-known JavaScript library to upload images using a variaty of uploader runtimes. It provides an HTML4 and an HTML5 runtime but also a Flash and a Silverlight runtime. You can configure a list of runtimes. Plupload will check for you which one is available on the particular client.

The usual way to use Plupload is to let the user select files with a native dialog or using drag&drop. You then upload the file to some server side business logic and display the progress. In my case, I wanted something different. First I want to show the selected image to the user and second I want to store the image not on the server but in a model on the client (which contains other data and will eventually be stored somewhere).

In this article, I will describe how to display a preview of the image in a canvas and how to convert the image to a Data URI.

First you need to deploy Plupload on your web server and reference it’s JavaScript file e.g.:

<script src="vendor/plupload/plupload.full.min.js"></script>

Then you need to have some HTML code to define a button which will be clicked by the user to open the file browser and a tag to display the image preview:

<a href="" type="button" id="selectfiles">Select</a>
<div id="preview"></div>

Now you’ll have to write some JavaScript code to initialize Plupload:

var uploader = new plupload.Uploader({
	runtimes: 'html5,flash,silverlight',
	browse_button: 'selectfiles',
	multi_selection: false,
	url: "about:blank",
	flash_swf_url: 'vendor/plupload/Moxie.swf',
	silverlight_xap_url: 'vendor/plupload/Moxie.xap',
	filters: [{title: "Image files", extensions: "jpg,gif,png"}]
});

uploader.init();

We’ve defined that Plupload should use the selectfiles element to let the user open the file browser. If you use the Flash and/or Silverlight runtimes, you have to point Plupload to the URL of those SWF and XAP files. And we define that a user can only choose one file and that it needs to be a GIF, JPEG or PNG file. This all pretty standard.

The only special trick is that we use “about:blank” as URL for the upload. Actually, you can specify whatever you want. It just needs to be a non-empty string. Otherwise Plupload will not initialize successfully. But since we won’t use Plupload to actually upload the file, we do not care about the value of this option, as long as it is defined.

Then we’ll want to be notified when the user as selected a file. So we need to register for an event:

uploader.bind("FilesAdded", filesAdded);

function filesAdded (uploader, files) {}

Now we’ll implement the filesAdded function. It will get the selected file and will need to embed that image in canvas in our preview element. Luckily, Plupload provides us with an Image class which provides us with all we need to do this:

function filesAdded (uploader, files) {
	$.each(files, function () {
		var img = new mOxie.Image();
		img.onload = function () {
			$('#preview').empty();
			this.embed($('#preview').get(0), {
				width: 100,
				height: 100
			});
		};
		img.onembedded = function () {
			this.destroy();
		};
		img.onerror = function () {
			this.destroy();
		};
		img.load(this.getSource());
	});
};

Now once the user select a file, it will be displayed as a preview. Now once the user decides to save, we can use this preview to save the image (note that this works in my case because I only want to store a 100×100 image and do not need the original image):

var dataURI = $("#preview canvas")[0].toDataURL();

Now you can store the data URI however you want.

Additionally, if you have a previously stored data URI and want to display it in the preview area, you can use the following code:

$('#preview').empty();
var $canvas = $("<canvas></canvas>");
$('#preview').append($canvas);
var context = $canvas.get(0).getContext('2d');
$canvas.attr('width', '100');
$canvas.attr('height', '100');
$('#preview').append($canvas);
var image = new Image();
image.onload = function () {
	context.drawImage(image, 0, 0, 100, 100);
};
image.src = $scope.data.user.image;

It just creates a canvas, loads the data URI in an Image object and has it drawn in the canvas’ 2D context.

2 thoughts on “Plupload: previewing images and getting Data URI

Leave a Reply

Your email address will not be published. Required fields are marked *