1

I made a code to get the camera feed in javascript using getusermedia in html5. Now what i want is to send that image to my c# api. I already this a question that is related to this, Sending base64 string to c# server but no luck. So I just want to ask what are the other way to send an image from html5 and javascript to my c# server.

Community
  • 1
  • 1
Hope
  • 644
  • 2
  • 6
  • 21

2 Answers2

1

Found an interesting article on this one over at Ode To Code. It shows how to write both the JavaScript and C# code to handle posting the content of an image captured from an HTML5 video element (from the previous blog post) to a C# ASP.NET server. His code is not too difficult to follow. I'd do the Regex a little differently, but it should work for you.

You can 'capture' the current content of a video object by drawing it to an HTML canvas, then convert the content of the canvas to a data: URI that you can post to your C# application.

The fun part is converting that data: URI back into an image, which the Ode To Code article shows you how to do. What you do with it after that is up to you. The O2C code saves it to disk, but you could run it through a MemoryStream and load it into memory using System.Drawing.Image.FromStream or similar.

Corey
  • 15,524
  • 2
  • 35
  • 68
  • thanks Corey. this is what i did at the moment. My problem is that i will get an error if i try to send base64 string to server. http://stackoverflow.com/questions/23950526/sending-base64-string-to-c-sharp-server – Hope Jun 02 '14 at 06:36
  • The CORS error you're getting is to do with cross-site stuff. Are you trying to post the captured frame to a different website than the one hosting the page? – Corey Jun 02 '14 at 06:38
  • im trying to post the captured frame to another computer. Actually the problem only occur when i try to send a very long base64 string. But when I try to send a short string then everything will work fine. – Hope Jun 02 '14 at 06:56
  • Hopefully my response to your other question will help. Make sure you're using Fiddler or similar to monitor what is actually happening. – Corey Jun 02 '14 at 07:05
0

Second answer, combining the CORS issue, tested locally.

Tested C# code (attribute and ApiController):

[AttributeUsage(AttributeTargets.Method)]
public class AllowReferrerAttribute : ActionFilterAttribute
{
    /// <summary>Update headers with CORS 'Access-Control-Allow-Origin' as required</summary>
    /// <param name="actionContext">Context of action to work with</param>
    public override void OnActionExecuting(HttpActionContext actionContext)
    {
        var ctx = (System.Web.HttpContextWrapper)actionContext.Request.Properties["MS_HttpContext"];
        var referrer = ctx.Request.UrlReferrer;

        if (referrer != null)
        {
            string refhost = referrer.Host;
            string thishost = ctx.Request.Url.Host;
            if (refhost != thishost)
                ctx.Response.AddHeader("Access-Control-Allow-Origin", string.Format("{0}://{1}", referrer.Scheme, referrer.Authority));
        }
        base.OnActionExecuting(actionContext);
    }
}

public class TestController : ApiController
{
    [AllowReferrer]
    public void Post([FromBody]string value)
    {
        if (value == null)
            throw new HttpResponseException(HttpStatusCode.BadRequest);
        if (value.Length > 100000)
            throw new HttpResponseException(HttpStatusCode.Forbidden);
    }
}

JavaScript code to invoke:

function imgToBase64(img)
{
    var canvas = document.createElement('CANVAS');
    var ctx = canvas.getContext('2d');
    canvas.height = img.height;
    canvas.width = img.width;
    ctx.drawImage(img, 0, 0);
    var dataURL = canvas.toDataURL('image/jpeg');
    $(canvas).remove();
    return dataURL;
}

$.ajax({ url: 'http://localhost:63905/api/Test', type: 'POST', data: "=" + imgToBase64($('img')[0]), crossDomain: true })

To test I copied the above code into the console of a browser with a foreign page (on one of my servers) loaded, where the first image on the page was a nice big one. Data arrives as expected in the value parameter, and returns a 403 error because it's over 100,000 bytes in size.

The tricks are:

  1. You have to have a [FromBody] parameter in your Post handler.

  2. The data passed to the $.ajax call must be a string with an = character at the start. This is just the way things work with ApiController and [FromBody]. The = character will be stripped.

The AllowReferrer attribute will stop your JavaScript code from giving errors when you try to do an AJAX POST to a different site, but that's all. It just stops you reporting back to your JavaScript as to what you did with the data it posted. The POST will generally still be processed by your controller.

If the site you're on fails it's probably because of cross-site scripting headers like x-xss-protection:1; mode=block in the response when the image was served. A lot of sites now set these headers as easy protection against simple DNS poisoning attacks and so on. This will cause an error along the lines of:

SecurityError: Failed to execute 'toDataURL' on 'HTMLCanvasElement': Tainted canvases may not be exported.

If you get that error then you're up against a CORS issue and there's not much you can do about it. If you're working with your own code then it's not a problem, it's when you're trying to grab stuff from other sites that CORS is an issue.

And no, I'm not going to even start telling you how to break CORS. That's not what Stack Overflow is for.

Corey
  • 15,524
  • 2
  • 35
  • 68