MVC WebAPI return multiple images - c#

I have 3 images in a directory but my code always returns one of them. I'd like to return 3 images image1.jpg, image2.jpg, image3.jpg and get them in my Xamarin app.
I think returning the result like an array might solve the problem but I don't understand what I need.
var result = new HttpResponseMessage(HttpStatusCode.OK);
MemoryStream ms = new MemoryStream();
for (int i = 0; i < 3; i++)
{
String filePath = HostingEnvironment.MapPath("~/Fotos/Empresas/Comer/" + id + (i + 1) + ".jpg");
FileStream fileStream = new FileStream(filePath, FileMode.OpenOrCreate);
Image image = Image.FromStream(fileStream);
image.Save(ms, ImageFormat.Jpeg);
fileStream.Close();
byte[] bytes = File.ReadAllBytes(filePath);
byte[] length = BitConverter.GetBytes(bytes.Length);
// Write length followed by file bytes to stream
ms.Write(length, 0, 3);
ms.Write(bytes, 0, bytes.Length);
}
result.Content = new StreamContent(ms);
return result;
Now i getting bytes, i edit a little bit the code now
byte[] imageAsBytes = client.GetByteArrayAsync(url).Result;
MemoryStream stream1 = new MemoryStream(imageAsBytes);
img.Source = ImageSource.FromStream(() => { return stream1; });
this is my xamarin code to get images, but i still getting nothing =/

If you just return a memorystream is not easy to differentiate one image from the other in the stream, instead of this, you can return a List of byte arrays, then you can access each position in the array and convert from byte array to image...
Here is a fully functional dotnet core webapi controller :
public class GetImagesController : Controller
{
private readonly IWebHostEnvironment _host;
public GetImagesController(IWebHostEnvironment host)
{
_host = host;
}
[HttpGet("{images}")]
public async Task<List<byte[]>> Get([FromQuery]string images)
{
List<byte[]> imageBytes = new List<byte[]>();
String[] strArray = images.Split(',');
for (int i = 0; i < strArray.Length; i++)
{
String filePath = Path.Combine(_host.ContentRootPath, "images", strArray[i]+".jpg");
byte[] bytes = System.IO.File.ReadAllBytes(filePath);
imageBytes.Add(bytes);
}
return imageBytes;
}
}
This controller can be called like this :
https://localhost:44386/getImages?images=P1,P2,P3
Given that you have a folder called images with files P1.jpg, P2.jpg and P3.jpg under your ContentRooPath.
https://learn.microsoft.com/en-us/aspnet/core/fundamentals/host/web-host?view=aspnetcore-3.0

You'll need something in the response to delimit where each image starts and finishes. As a basic solution, you could write the image length as an Int32 and follow it with the image data. On the other end, you'll need to read the 4-byte length followed by that x number of bytes:
[HttpGet]
public HttpResponseMessage Get(string id)
{
var result = new HttpResponseMessage(HttpStatusCode.OK);
String[] strArray = id.Split(',');
var ms = new MemoryStream();
for (int i = 0; i < strArray.Length; i++)
{
String filePath = HostingEnvironment.MapPath("~/Fotos/Empresas/Comer/" + strArray[i] + (i + 1) + ".jpg");
byte[] bytes = File.ReadAllBytes(filePath);
byte[] length = BitConverter.GetBytes(bytes.Length);
// Write length followed by file bytes to stream
ms.Write(length, 0, 4);
ms.Write(bytes, 0, bytes.Length);
}
result.Content = new StreamContent(ms);
return result;
}

Related

Problem converting Image to Base64 in Blazor Server

So I am trying to convert an image base64 that will be uploaded to SQL Server.
Current code is:
private async Task OnInputFileChange(InputFileChangeEventArgs args)
{
var maxFiles = 1;
var maxSize = 512000000;
var format = "image/jpg";
test = "Something";
test1 = args.FileCount.ToString();
foreach (var file in args.GetMultipleFiles(maxFiles))
{
var image = await file.RequestImageFileAsync(format, 500, 500);
test = image.Size.ToString();
buffer = new byte[image.Size];
await image.OpenReadStream(maxAllowedSize: maxSize).ReadAsync(buffer);
test1 = buffer.ToString();
var imageDataUrl = $"data:{format};base64,{Convert.ToBase64String(buffer)}";
imageDataUrls.Add(imageDataUrl);
imageString = imageDataUrl;
}
}
It begins fine, however only the top portion of image is actually converted and in the string is followed by thousands of repeating "A". Reconstructing the image just shows the top portion of the image. What am I doing wrong?
Currently I had not uploaded and redownloaded the string, it is all local until I can figure out what is wrong. I am using the imageString for the image source. I am using .net 6.0.
Try this. Works for me. Files since 1 MB.
public static byte[] GetBytes(Stream stream)
{
var bytes = new byte[stream.Length];
stream.Seek(0, SeekOrigin.Begin);
stream.ReadAsync(bytes, 0, bytes.Length);
stream.Dispose();
return bytes;
}
private async Task OnInputFileChange(InputFileChangeEventArgs args)
{
string base64String = "";
try
{
var files = args.GetMultipleFiles();
foreach (var file in files)
{
await using MemoryStream fs = new MemoryStream();
await file.OpenReadStream(maxAllowedSize: 1048576).CopyToAsync(fs);
byte[] somBytes = GetBytes(fs);
base64String = Convert.ToBase64String(somBytes, 0, somBytes.Length);
System.Diagnostics.Debug.Print("Imatge 64: " + base64String + Environment.NewLine);
}
}
catch (Exception e)
{
System.Diagnostics.Debug.Print("ERROR: " + e.Message + Environment.NewLine);
}
}

Cannot append value to string C#

I've got two methods in my Windows Forms application for parsing some gzip encoded strings.
Here are my two methods, which both return the same value.
public static async Task<string> DecodeGzipAsync(string str)
{
var values = new Dictionary<string, string>
{
{ "data", str }
};
var content = new FormUrlEncodedContent(values);
var client = new HttpClient();
var response = await client.PostAsync("http://www.txtwizard.net/compression/decompress/gz", content);
var json = await response.Content.ReadAsStringAsync();
var result = JsonConvert.DeserializeObject<GzipData>(json);
return result.DecompressedData;
}
public static string DecodeGzip(string str)
{
byte[] gzBuffer = Convert.FromBase64String(str);
using (MemoryStream ms = new MemoryStream())
{
int msgLength = BitConverter.ToInt32(gzBuffer, 0);
ms.Write(gzBuffer, 0, gzBuffer.Length);
byte[] buffer = new byte[msgLength];
ms.Position = 0;
using (GZipStream zip = new GZipStream(ms, CompressionMode.Decompress))
{
zip.Read(buffer, 0, buffer.Length);
}
return Encoding.UTF8.GetString(buffer);
}
And then I call these two methods from my main form.
var string1 = await Utilities.DecodeGzipAsync(xml.InnerText);
var string1Concat = string.Concat("<Connotes>", string1, "</Connotes>");
var string2 = Utilities.DecodeGzip(xml.InnerText);
var string2Concat = string.Concat("<Connotes>", string2, "</Connotes>");
Where xml.InnerText is
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
The results I get are really frustrating (and weird!)
string1 and string2 both return the same string, however string1Concat and string2Concat return different results.
string1Concat = "<Connotes>" + string1 + "</Connotes>"
string2Concat = "<Connotes>" + string2 // Notice how it is missing the concatenation on the end
What might be causing this behaviour? I have tried changing the encoding to ASCII and UTF8 but both give the same results.
Any help is much appreciated!
This was a little tricky, but I found the problem/solution:
You convert the array of the size of the compressed data to a string at Encoding.UTF8.GetString(buffer). This will create a string which a length of 559903 instead of the correct 9209. If you create a new byte-array with the actually read bytes it is working:
public static string DecodeGzip(string str)
{
byte[] gzBuffer = Convert.FromBase64String(str);
using (MemoryStream ms = new MemoryStream())
{
int msgLength = BitConverter.ToInt32(gzBuffer, 0);
ms.Write(gzBuffer, 0, gzBuffer.Length);
byte[] buffer = new byte[msgLength];
ms.Position = 0;
int length;
using (GZipStream zip = new GZipStream(ms, CompressionMode.Decompress))
{
length = zip.Read(buffer, 0, buffer.Length);
}
var data = new byte[length];
Array.Copy(buffer, data, length);
return Encoding.UTF8.GetString(data);
}
}

FileStream is not working with relative path

I'm trying to use a FileStream with a relative path but it is not working.
var pic = ReadFile("~/Images/money.png");
It is working when I use something like:
var p = GetFilePath();
var pic = ReadFile(p);
the rest of the code(from SO):
public static byte[] ReadFile(string filePath)
{
byte[] buffer;
FileStream fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read);
try
{
int length = (int)fileStream.Length; // get file length
buffer = new byte[length]; // create buffer
int count; // actual number of bytes read
int sum = 0; // total number of bytes read
// read until Read method returns 0 (end of the stream has been reached)
while ((count = fileStream.Read(buffer, sum, length - sum)) > 0)
sum += count; // sum is a buffer offset for next reading
}
finally
{
fileStream.Close();
}
return buffer;
}
public string GetFilePath()
{
return HttpContext.Current.Server.MapPath("~/Images/money.png");
}
I don't get why it is not working because the FileStream constructor allow using relative path.
I'm assuming the folder in your program has the subfolder images, which contains your image file.
\folder\program.exe
\folder\Images\money.jpg
Try without the "~".
I also had the same issue but I solved it by using this code,
Try one of this code, hope it will solve your issue too.
#region GetImageStream
public static Stream GetImageStream(string Image64string)
{
Stream imageStream = new MemoryStream();
if (!string.IsNullOrEmpty(Image64string))
{
byte[] imageBytes = Convert.FromBase64String(Image64string.Substring(Image64string.IndexOf(',') + 1));
using (Image targetimage = BWS.AWS.S3.ResizeImage(System.Drawing.Image.FromStream(new MemoryStream(imageBytes, false)), new Size(1600, 1600), true))
{
targetimage.Save(imageStream, ImageFormat.Jpeg);
}
}
return imageStream;
}
#endregion
2nd one
#region GetImageStream
public static Stream GetImageStream(Stream stream)
{
Stream imageStream = new MemoryStream();
if (stream != null)
{
using (Image targetimage = BWS.AWS.S3.ResizeImage(System.Drawing.Image.FromStream(stream), new Size(1600, 1600), true))
{
targetimage.Save(imageStream, ImageFormat.Jpeg);
}
}
return imageStream;
}
#endregion

MVC 4 Reading bytes from HttpPostedFileBase

I what to read the bytes of a docx file and I have this method:
public ActionResult Create(Model myModel, HttpPostedFileBase fileUpload)
{
MemoryStream ms = new MemoryStream();
byte[] bin = new byte[100];
long rdlen = 0;
long totlen = fileUpload.InputStream.Length;
int len;
while (rdlen < totlen)
{
len = fileUpload.InputStream.Read(bin, 0, 100);
ms.Write(bin, 0, len);
rdlen += len;
}
}
the total length of the file is 11338 but it only reads until 11326 then it stuck in an infinite loop because when it reaches the 11326 this len = fileUpload.InputStream.Read(bin, 0, 100); will only return 0 as a value. The weird thing is that if I upload a txt file it work as it should.
Thanks
byte[] myFile;
using (var memoryStream = new MemoryStream())
{
httpPostedFileBase.InputStream.CopyTo(memoryStream);
myFile = memoryStream.ToArray();// or use .GetBuffer() as suggested by Morten Anderson
}
This works, im using it myself for images uploaded.
public ActionResult Create(Model myModel, HttpPostedFileBase fileUpload)
{
byte[] Data = null;
using (var binaryReader = new BinaryReader(fileUpload.InputStream))
{
Data = binaryReader.ReadBytes(fileUpload.ContentLength);
}
}

zlib.net code example for C# that take byte[] as input agument

I spent 3 hours searching for how to uncompress a string using Zlib.net.dll and I did not find anything useful.
Since my string is compressed by the old VB6 program that uses zlib.dll and I do not want to use file access each time I want to uncompress a string.
The problem is you need to know what the original size of the byte[] is before compression.
Or you can use dynamic array for decoding the data.
The code is here:
private string ZlibNetDecompress(string iCompressData, uint OriginalSize)
{
byte[] todecode_byte = Convert.FromBase64String(iCompressData);
byte[] lDecodeData = new byte[OriginalSize];
string lTempoString = System.Text.Encoding.Unicode.GetString(todecode_byte);
todecode_byte = System.Text.Encoding.Default.GetBytes(lTempoString);
string lReVal = "";
MemoryStream outStream = new MemoryStream();
MemoryStream InStream = new MemoryStream(todecode_byte);
zlib.ZOutputStream outZStream = new zlib.ZOutputStream(outStream);
try
{
CopyStream(InStream, outZStream);
lDecodeData = outStream.GetBuffer();
lReVal = System.Text.Encoding.Default.GetString(lDecodeData);
}
finally
{
outZStream.Close();
InStream.Close();
}
return lReVal;
}
private void CopyStream(System.IO.Stream input, System.IO.Stream output)
{
byte[] buffer = new byte[2000];
int len;
while ((len = input.Read(buffer, 0, 2000)) > 0)
{
output.Write(buffer, 0, len);
}
output.Flush();
}
You could use the GZipStreamClass from the framework.
var data = new byte[resultSizeMax];
using (Stream ds = new DeflateStream(stream, CompressionMode.Decompress))
for (var i=0; i< 1000; i+=ds.Read(data, i,1000-i);

Categories