9

I'm trying to return a base64 string representing a jpeg image from an API Controller and set it as the src of an <img> but all my attempts failed.

Here is the very simple HTML:

<img src="/api/TestBase64Image" alt="image test" />

And my controller:

[Route("api/[controller]")]
public class TestBase64ImageController : Controller
{
    private const string _base64Image = "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEBLAEsAAD/7Sfg.....";
    private const string _base64Image2 = "/9j/4AAQSkZJRgABAQEBLAEsAAD/7Sfg.....";

    [HttpGet]
    public async Task Get()
    {
        Response.ContentType = "image/jpeg";
        //Response.ContentType = "text/plain";
        //Response.ContentType = new MediaTypeHeaderValue("image/jpeg").ToString();
        //Response.ContentType = new MediaTypeHeaderValue("text/plain").ToString();

        //Response.Headers.Add("Content-Length", _base64Image.Length.ToString());
        //HttpContext.Response.ContentLength = _base64Image.Length;

        await Response.Body.WriteAsync(Encoding.UTF8.GetBytes(_base64Image), 0, _base64Image.Length);
        //await Response.Body.FlushAsync();
    }
}

I've tried several things, like removing FlushAsync(), changing the way to define the ContentType, include data:image/jpeg;base64, in the string or not but nothing is working.

I've seen here and here that writing in the Response body stream is doable, so I presume I'm on the good way (I've tried to return a simple string before but not working as well).

Yes my base64 string is correct because I've also tried to include it directly into the HTML and the image shows up correctly.

I precise I don't want to use any JavaScript or Razor view to achieve that, only pure HTML and my controller.

Also please pay attention that I'm inside an API Controller. I can't do the same as we see in the Configure method in the Startup class of an empty ASP.NET Core project like:

app.Run(async (context) =>
{
    await context.Response.WriteAsync("Hello World!");
});

Even though both Responses' types are HttpResponse, the one in my controller doesn't have any Response.WriteAsync but Response.Body.WriteAsync

Thanks for your help, it's been hours I'm searching but there is almost no resources about this yet for ASP.NET Core

Jérôme MEVEL
  • 7,031
  • 6
  • 46
  • 78
  • 1
    Why are you trying to return a base64 image when it's requested? The point of base64 data URIs is to embed the data within the HTML. For just a regular image fetch, you should return the binary data directly. – Jon Skeet Oct 12 '16 at 09:09
  • I'm in a context of having the image as a base64 string, I don't have any physical file to serve. But isn't it what I'm doing, returning binary data using `Encoding.UTF8.GetBytes`? I'm lost the way to do this because in old ASP.NET (non-MVC) I did that using `Response.BinaryWrite` but there is no such thing in Core... – Jérôme MEVEL Oct 12 '16 at 09:14
  • 2
    For the record, the reason your controller code does not have "Response.WriteAsync()" is because you did NOT include the namespace with the required extension method. ;) Add `using Microsoft.AspNetCore.Http;` to your controller page and it will be there. TIP: If you type the extension method name, VS will try to resolve it for you with the quick action prompt. – James Wilkins Mar 15 '17 at 21:46
  • I had a similar problem and the solution worked! Just add the package from "Manage NuGet packages" and then install: Microsoft.AspNetCore.Http.Abstractions "version = 1.1.2" (in my case). Finally in the source code, I added: using Microsoft.AspNetCore.Http; Thanks for help! – Mateo Moncada Roldán Jul 25 '17 at 01:30

1 Answers1

15

You're still returning the data as base64 text, basically - you're getting the UTF-8 encoded form of it, but that's all.

If you really only have the base64 version of the image, you just need to decode that:

byte[] image = Convert.FromBase64String(_base64Image2);
await Response.Body.WriteAsync(image, 0, image.Length);

(Note that it needs to be just the base64 you convert - not the data URI.)

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • Wow the solution was so simple, I'm wondering how I missed that... Super fast answer, thanks a lot Jon. (`WriteAsync` is also waiting the `offset` and the `length`, I let you edit your answer...) – Jérôme MEVEL Oct 12 '16 at 09:23