Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's the best way to serve up multiple binary files from a single WebApi method?

I have an ASP.NET MVC 4 Web Api controller method that gets passed a list of file IDs and returns thumbnail images for those files.

So, the client might pass in a list of numeric IDs (e.g. 10, 303, 29), and the method returns a List where a ThumbnailImage looks a bit like this:

class ThumbnailImage
{
    public int Id { get; set; }
    // Some other stuff
    public byte[] RawData { get; set; }
}

The reason that the caller passes in a list of IDs rather than making one call per item should hopefully be obvious - there may be dozens or hundreds of items to download, and I'm trying to avoid all the HTTP traffic that would be required to download them individually.

Currently, I'm using RestSharp and JSON.NET, and so my ThumbnailImage objects are being passed across the wire as JSON. It's fine from a simplicity-of-coding point of view, but JSON is not an efficient way to represent that binary data.

So, I'm thinking that I should return the raw bytes as an octet-stream... however, while I can easily do that for a single image, I'm not sure of the best way to do it for multiple images, especially when I also need to return the ID and miscellaneous other information for each file. (The ID is required since the results will not necessarily be returned in a given order - and some files may be missing).

I could simply write everything piecemeal into the response stream, so that for each item I write the ID (suitably encoded), followed by the length of the image data, followed by the image data itself, and then followed by the same thing for the next item, etc.

The caller would then simply keep reading from the stream until it was exhausted, making assumptions about the encoding (and length!) of the IDs, etc.

I think that would work, but it seems clunky - is there a better way?

like image 601
Gary McGill Avatar asked Sep 04 '12 15:09

Gary McGill


People also ask

How can we return multiple types of responses from Web API?

use ActionResult as the return type on the action method in the controller class.

Can we have multiple get methods in Web API?

As mentioned, Web API controller can include multiple Get methods with different parameters and types. Let's add following action methods in StudentController to demonstrate how Web API handles multiple HTTP GET requests.

How many get methods we can implement in single controller in Web API?

Usually a Web API controller has maximum of five actions - Get(), Get(id), Post(), Put(), and Delete().


3 Answers

OK, here's a snippet of code that seems to work, using the MultipartContent that KiranChalla referred to. (This is just a dummy sample that shows how to return two files of different types, in conjunction with a JSON-encoded "object" (which in this case is just a list of integer IDs).

public HttpResponseMessage Get()
{
    var content = new MultipartContent();
    var ids = new List<int>() { 1, 2 };

    var objectContent = new ObjectContent<List<int>>(ids, new System.Net.Http.Formatting.JsonMediaTypeFormatter());
    content.Add(objectContent);

    var file1Content = new StreamContent(new FileStream(@"c:\temp\desert.jpg", FileMode.Open));
    file1Content.Headers.ContentType = System.Net.Http.Headers.MediaTypeHeaderValue.Parse("image/jpeg");
    content.Add(file1Content);

    var file2Content = new StreamContent(new FileStream(@"c:\temp\test.txt", FileMode.Open));
    file2Content.Headers.ContentType = System.Net.Http.Headers.MediaTypeHeaderValue.Parse("text/plain");
    content.Add(file2Content);

    var response = new HttpResponseMessage();
    response.Content = content;
    return response;
}
like image 86
Gary McGill Avatar answered Oct 13 '22 02:10

Gary McGill


You could create a compressed file (e.g. a ZIP file) out of all the thumbnails and send that back.

Then the caller just has to unzip it their end - sending a single file containing multiple files is going to be far more acceptable then sending multiple files in a single stream.

Disadvantage is you're less likely to be able to take advantage of caching (depending on your usage patterns of course).

like image 22
RB. Avatar answered Oct 13 '22 02:10

RB.


One challenge I see is that based on the number of images being sent back the caller has to adjust their timeout value. If this was for a book store, there could be a lot of images sent back.

What if you only sent back the urls for each image and leave it up to the caller to get the actual image? It would mean a little more traffic with multiple calls but the caller would get back information sooner than later and then get the images based on the caller's requirement.

I could be wrong, but I thought the idea behind rest was to identify each resource versus bundling a bunch of images and calling that a resource. Just a thought...

like image 1
SainathDK Avatar answered Oct 13 '22 01:10

SainathDK