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.
OdeToCode by K. Scott Allen