Can't convert a Base64 to MemoryStream - c#

I'm having some issues in converting an image from an Base63 string to image memoryStream on a WebApi. The result looks like this:
I have tried several ways ala this:
var imageBytes = Convert.FromBase64String(pagedResult.Data);
var ms = new MemoryStream(imageBytes, 0, imageBytes.Length);
var image = await Image.LoadAsync(ms, cancellationToken);
var stream = new MemoryStream();
await image.SaveAsync(stream, new JpegEncoder(), cancellationToken);
stream.Position = 0;
ms.Position = 0;
return (stream, pagedResult.Mimetype);
Or something as simple like this:
var sapDoc = Convert.FromBase64String(pagedResult.Data);
return (new MemoryStream(sapDoc), pagedResult.Mimetype);
The controller looks like this:
[HttpGet("document")]
public async Task<ActionResult<Stream>> GetImage([FromQuery] long documentNumber, string documentId)
{
var query = new GetDocument.Query
{
DocumentId = documentId,
DocumentNumber = documentNumber
};
var (image, imageFormat) = await _mediator.Send(query);
return File(image, imageFormat);
Any idea what's going on?
I have verified the base64 string. If i take the output and use forexample this: https://codebeautify.org/base64-to-image-converter i can see the image.

I found the issue. I was the mimType that from SAP was set to JPG instead of JPEG. An simple mimType.Replace("jpg", "jpeg") fixed the issue :)

Here is a way to do it:
var data = Encoding.UTF8.GetBytes(pagedResult.Data);
MemoryStream stream = new MemoryStream();
stream.Write(data, 0, data.Length);

Related

Blazor download html string as Image

public async Task ExportGraph(string projectName, string html)
{
var bytes = Encoding.Default.GetBytes(html);
using var stream = new MemoryStream(bytes);
stream.Seek(0, SeekOrigin.Begin);
using var streamRef = new DotNetStreamReference(stream: stream);
await JS.InvokeVoidAsync("downloadFileFromStream", $"FazerGraph-{projectName}.jpg", streamRef);
}
I have this method that receives a string containing the html I want to create an image from.
I-m getting this string from this JS method:
function getInnerHTMLElement(element) {
if (element) {
return element.innerHTML;
}
return null;
}
When I download the jpg image and try to open it says:
What I'm doing wrong?
I'm using now html converter like this:
public async Task ExportGraph(string projectName, string html)
{
var converter = new HtmlConverter();
var bytes = converter.FromHtmlString(html);
using var stream = new MemoryStream(bytes);
stream.Seek(0, SeekOrigin.Begin);
using var streamRef = new DotNetStreamReference(stream: stream);
await JS.InvokeVoidAsync("downloadFileFromStream", $"FazerGraph-{projectName}.jpg", streamRef);
}
and the result image I get is this:
What can I do to make it the same look like the html (shown bellow)?

Converting String to Stream

So I am trying to serialize and deserialize an IReadOnlyList<InkStroke> from Windows.UI.Input.Inking for my UWP app, and I have used the following code to serialize the data:
var stream = new InMemoryRandomAccessStream();
await canvas.InkPresenter.StrokeContainer.SaveAsync(stream);
await stream.FlushAsync();
var buffer = new byte[stream.Size];
await stream.AsStream().ReadAsync(buffer, 0, buffer.Length);
return Convert.ToBase64String(buffer);
How can I deserialize this string to create an IInputStream (or IRandomAccessStream instead) which can be used in the StrokeContainer.LoadAsync() method?
You can use the following piece of code....
byte[] bytes = Convert.FromBase64String(stringinput);
MemoryStream stream = new MemoryStream(bytes);
IInputStream is=stream.AsRandomAccessStream(); //It will return an IInputStream object
Try this:
byte[] data = Convert.FromBase64String(encodedString);
InMemoryRandomAccessStream inputStream = new InMemoryRandomAccessStream();
await inputStream.WriteAsync(data.AsBuffer());
inputStream.Seek(0);
await canvas.InkPresenter.StrokeContainer.LoadAsync(inputStream);

Load an image from URL as base64 string

I am trying to load an image as a base 64 string so that i can show it in a html like this:
<html><body><img src="data:image/jpeg;base64,/></img></body></html>
Heres my code so far, but it does not really work:
public async static Task<string> getImage(string url)
{
var request = (HttpWebRequest)WebRequest.Create(url);
request.Accept = "data:image/jpg;charset=base64";
request.Credentials = new NetworkCredential(user, pw);
using (var response = (HttpWebResponse)(await Task<WebResponse>.Factory.FromAsync(request.BeginGetResponse, request.EndGetResponse, null)))
{
StreamReader sr = new StreamReader(response.GetResponseStream());
return sr.ReadToEnd();
}
I tried using this method i found elsewhere to encode the return-String as base64, but when placing it in a html the image just shows the typical placeholder.
public static string Base64Encode(string plainText)
{
var plainTextBytes = System.Text.Encoding.UTF8.GetBytes(plainText);
return System.Convert.ToBase64String(plainTextBytes);
}
EDIT:
Here is how the html looks:
It seems to me that you need to separate the base64 part, which is only needed in your HTML, from fetching the data from the response. Just fetch the data from the URL as binary data and convert that to base64. Using HttpClient makes this simple:
public async static Task<string> GetImageAsBase64Url(string url)
{
var credentials = new NetworkCredential(user, pw);
using (var handler = new HttpClientHandler { Credentials = credentials })
using (var client = new HttpClient(handler))
{
var bytes = await client.GetByteArrayAsync(url);
return "image/jpeg;base64," + Convert.ToBase64String(bytes);
}
}
This assumes the image always will be a JPEG. If it could sometimes be a different content type, you may well want to fetch the response as an HttpResponse and use that to propagate the content type.
I suspect you may want to add caching here as well :)
using (HttpClient client = new HttpClient())
{
try
{
using (Stream stream = await client.GetStreamAsync(uri))
{
if (stream == null)
return (Picture)null;
byte[] buffer = new byte[16384];
using (MemoryStream ms = new MemoryStream())
{
while (true)
{
int num = await stream.ReadAsync(buffer, 0, buffer.Length, cancellation);
int read;
if ((read = num) > 0)
ms.Write(buffer, 0, read);
else
break;
}
imageData = Convert.ToBase64String(ms.ToArray());
}
buffer = (byte[])null;
}
}
catch (Exception ex)
{
}
}
You must first get the image from disk, then convert it to byte[] and then again to base64.
public string ImageToBase64(Image image, System.Drawing.Imaging.ImageFormat format)
{
using (MemoryStream ms = new MemoryStream())
{
// Convert Image to byte[]
image.Save(ms, format);
byte[] imageBytes = ms.ToArray();
// Convert byte[] to Base64 String
string base64String = Convert.ToBase64String(imageBytes);
return base64String;
}
}

After fileStream.CopyTo(memoryStream), memoryStream is null

So, I have the function, which gets BitmapImage, I need to save it to iso storage and convert to Base64 (for sending to server). However, copying from fileStream to memoryStream is not successful.
public void SetImage(BitmapImage bitmap)
{
if (isoFiles.FileExists(Settings.FILE_AVATAR_JPG))
isoFiles.DeleteFile(Settings.FILE_AVATAR_JPG);
var fileStream = isoFiles.CreateFile(Settings.FILE_AVATAR_JPG);
var wb = new WriteableBitmap(bitmap);
wb.SaveJpeg(fileStream, 120, 120, 0, 85); // file is saved
var memoryStream = new MemoryStream();
fileStream.CopyTo(memoryStream); // here, memoryStream is null
byte[] result = memoryStream.ToArray();
fileStream.Close();
var base64 = Convert.ToBase64String(result);
}
Stream.CopyTo copies from the current position of fileStream which has been changed by SaveJpeg() so you need to reset it;
var memoryStream = new MemoryStream();
fileStream.Position = 0;
fileStream.CopyTo(memoryStream);

Convert resource to byte[]

I am having trouble converting an image resource into byte[].
For example, I have the following resource:
pack://application:,,,/AppName;component/Assets/Images/sampleimage.jpg
in my program. How do I convert this into a byte[].
I've tried using a BitMapImage, but it's ImageSource ends up being null after initialised.
This seems to work:
var info = Application.GetResourceStream(uri);
var memoryStream = new MemoryStream();
info.Stream.CopyTo(memoryStream);
return memoryStream.ToArray();
A general solution to convert a BitmapSource into a byte[] would look like this:
public byte[] GetImageBuffer(BitmapSource bitmap, BitmapEncoder encoder)
{
encoder.Frames.Add(BitmapFrame.Create(bitmap));
using (var stream = new MemoryStream())
{
encoder.Save(stream);
return stream.ToArray();
}
}
You would use it like shown below, with any of the BitmapEncoders that are available in WPF.
var uri = new Uri("pack://application:,,,/AppName;component/Assets/Images/sampleimage.jpg");
var bitmap = new BitmapImage(uri);
var buffer = GetImageBuffer(bitmap, new JpegBitmapEncoder());

Categories