DevYuri
DevYuri

Reputation: 43

MVC WebAPI return multiple images

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 =/

Upvotes: 3

Views: 3860

Answers (2)

Mauricio Atanache
Mauricio Atanache

Reputation: 2581

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

Upvotes: 2

joehoper
joehoper

Reputation: 423

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;
}

Upvotes: 0

Related Questions