从单个Web Api方法提供多个二进制文件的最佳方法是什么?

时间:2012-09-04 15:11:14

标签: c# rest asp.net-web-api

我有一个ASP.NET MVC 4 Web Api控制器方法,它传递一个文件ID列表并返回这些文件的缩略图。

因此,客户端可能会传入一个数字ID列表(例如10,303,29),并且该方法返回一个List,其中ThumbnailImage看起来有点像这样:

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

调用者传入ID列表而不是每个项目进行一次调用的原因应该是显而易见的 - 可能有数十或数百个项目要下载,我试图避免所有HTTP流量需要单独下载它们。

目前,我正在使用RestSharp和JSON.NET,因此我的ThumbnailImage对象作为JSON通过网络传递。从简单编码的角度来看,它很好,但JSON不是表示二进制数据的有效方式。

所以,我认为我应该将原始字节作为八位字节流返回...但是,虽然我可以轻松地为单个图像执行此操作,但我不确定最佳方式为多个图像执行此操作,尤其是当我还需要为每个文件返回ID和其他其他信息时。 (该ID是必需的,因为结果不一定以给定的顺序返回 - 并且某些文件可能会丢失。)

可以简单地将所有内容零碎地写入响应流中,以便为每个项目编写ID(适当编码),然后是图像数据的长度,然后是图像数据本身,然后对下一个项目进行相同的操作,等等。

然后调用者将继续从流中读取,直到它耗尽为止,对ID的编码(和长度!)进行假设等。

我认为这样可行,但看起来很笨 - 有更好的方法吗?

3 个答案:

答案 0 :(得分:11)

好的,这里有一段似乎有用的代码,使用KiranChalla提到的MultipartContent。 (这只是一个虚拟示例,它显示了如何返回两个不同类型的文件,以及一个JSON编码的“对象”(在这种情况下只是一个整数ID列表)。

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

答案 1 :(得分:1)

我看到的一个挑战是,根据发回的图像数量,调用者必须调整其超时值。如果这是书店,可能会发回很多图片。

如果您只发回每张图片的网址并将其留给来电者以获取实际图片,该怎么办?这意味着多次呼叫会有更多的流量,但呼叫者会尽快收到信息,然后根据呼叫者的要求获取图像。

我可能错了,但我认为休息背后的想法是识别每个资源与捆绑一堆图像并将其称为资源。只是一个想法...

答案 2 :(得分:0)

您可以从所有缩略图中创建压缩文件(例如ZIP文件)并将其发回。

然后调用者必须将其解压缩 - 发送包含多个文件的单个文件比在单个流中发送多个文件更容易接受。

缺点是您不太可能利用缓存(当然,取决于您的使用模式)。