In "Capturing HTML 5 Video To An Image", Chris asked if we could upload a captured image to the server.
Yes we can!
We will use the same markup from the previous post, but make a simple change to the script. Instead of creating an image on the client, we'll send the image to the server by passing the dataURL generated from the canvas.
(function() { "use strict"; var video, $output; var scale = 1; var initialize = function() { $output = $("#output"); video = $("#video").get(0); $("#capture").click(captureImage); }; var captureImage = function() { var canvas = document.createElement("canvas"); canvas.width = video.videoWidth * scale; canvas.height = video.videoHeight * scale; canvas.getContext('2d') .drawImage(video, 0, 0, canvas.width, canvas.height); $.post("/image/upload", { dataUrl: canvas.toDataURL() }) .done(showImage); }; var showImage = function(url) { var img = document.createElement("img"); img.src = url; $output.prepend(img); }; $(initialize); }());
On the server we need to parse the incoming data URL. The data URL for an image will contain base 64 encoded bits, like the following:
data:image/png;base64,F12VBORw0KGgoAAAAN...==
The ImageDataUrl class will use a regex to pick apart the string and decode the bytes inside.
public class ImageDataUrl { public ImageDataUrl(string dataUrl) { var match = _regex.Match(dataUrl); MimeType = match.Groups["mimeType"].Value; Format = match.Groups["mimeSubType"].Value; Bytes = Convert.FromBase64String(match.Groups["data"].Value); } public byte[] Bytes { get; protected set; } public string MimeType { get; set; } public string Format { get; protected set; } public string SaveTo(string folder) { var fileName = Guid.NewGuid().ToString() + "." + Format; var fullPath = Path.Combine(folder, fileName); using(var file = File.OpenWrite(fullPath)) { file.Write(Bytes, 0, Bytes.Length); } return fileName; } private static readonly Regex _regex = new Regex( @"data:(?<mimeType>[\w]+)/(?<mimeSubType>[\w]+);\w+,(?<data>.*)", RegexOptions.Compiled ); }
The ImageDataUrl class can also save the decoded bytes to disk, so all we need to do inside of a controller action is use the class, and return a URL to the newly saved image.
[HttpPost] public string Upload(string dataUrl) { var image = new ImageDataUrl(dataUrl); var fileName = image.SaveTo(Server.MapPath("~/uploads")); var url = Url.Content("~/uploads/" + fileName); return url; }
That's one approach to uploading the image.