2012-09-04 15 views
14

Posiadam metodę kontrolera ASP.NET MVC 4 Web Api, która przekazuje listę identyfikatorów plików i zwraca obrazy miniatur dla tych plików.Jaki jest najlepszy sposób na serwowanie wielu plików binarnych za pomocą jednej metody WebApi?

Tak, klient może przejść na liście identyfikatorów numerycznych (np 10, 303, 29), a metoda zwraca List gdzie ThumbnailImage wygląda trochę jak ten:

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

tego powodu, że osoba dzwoniąca przechodzi na listę identyfikatorów, zamiast wykonywać jedno połączenie za przedmiot, mam nadzieję, że będzie oczywiste - do pobrania mogą być dziesiątki lub setki elementów i staram się unikać całego ruchu HTTP, który byłby wymagany do pobrania ich pojedynczo .

Obecnie używam RestSharp i JSON.NET, więc moje obiekty ThumbnailImage są przekazywane przez przewód jako JSON. Z punktu widzenia prostoty kodowania wszystko jest w porządku, ale JSON nie jest wydajnym sposobem reprezentowania danych binarnych.

Tak więc, myślę, że powinienem zwrócić surowe bajty jako strumień oktetu ... jednak, chociaż mogę to łatwo zrobić dla pojedynczego obrazu, nie jestem pewien, jak najlepiej to zrobić dla wielu obrazów, szczególnie gdy muszę również zwrócić ID i różne inne informacje dla każdego pliku. (Identyfikator jest wymagany, ponieważ wyniki niekoniecznie zostaną zwrócone w określonej kolejności - a niektórych plików może brakować).

I może po prostu napisać wszystko fragmentarycznie do strumienia odpowiedzi, tak aby dla każdej pozycji zapisałem identyfikator (odpowiednio zakodowany), a następnie długość danych obrazu, a następnie same dane obrazu, a następnie przez to samo dla następnego elementu itp

rozmówca będzie wtedy po prostu zachować czytania ze strumienia dopóki nie został wyczerpany, czyniąc założenia dotyczące kodowania (i długości!) z identyfikatorów itd

Myślę, że to by zadziałało, ale wydaje się nieporęczne - czy istnieje lepszy sposób?

+0

Jak będzie klient korzysta z obrazów? Czy obrazy do wyświetlenia na stronie internetowej lub do pobrania jako archiwum? Coś jeszcze? – EBarr

+0

Zastanawiasz się, czy możesz wysłać odpowiedź jako MultartContent, gdzie wewnętrzna zawartość mogłaby być StreamContent mająca surowy strumień bajtów –

+0

@EBarr: Piszę także aplikację kliencką, więc jest to zamknięte środowisko. Będę wyświetlał obrazy w aplikacji WinForms (jako miniatury wyników wyszukiwania). –

Odpowiedz

10

OK, oto fragment kodu, który wydaje się działać, używając MultartContent, o którym mowa w KiranChalla.(Jest to tylko atrapa przykładowy, który pokazuje w jaki sposób, aby powrócić dwa pliki różnych typów, w połączeniu z „obiekt” JSON zakodowane (który w tym przypadku jest tylko lista całkowitej identyfikatorów).

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

to nie działa dla mnie. Zwraca tylko jeden plik, który nie jest prawidłowym formatem. proszę pomóż mi. Utknąłem z tym –

0

Można utworzyć skompresowany plik (np. Plik ZIP) ze wszystkich miniatur i wysłać go z powrotem.

Następnie wywołujący musi rozpakować swój koniec - wysłanie pojedynczego pliku zawierającego wiele plików będzie znacznie bardziej akceptowalne, niż wysłanie wielu plików w jednym strumieniu.

Wadą jest mniejsza szansa na skorzystanie z buforowania (oczywiście w zależności od sposobu użytkowania).

+0

Ale nadal mam ten sam problem (choć w innym miejscu) przekazywania wszystkich powiązanych informacji (np. ID) ... Ponadto, nie widzę powodu, dla którego łatwiej jest rozpakować ZIP niż to rozpakuj połączony strumień plików? –

+1

@GaryMcGill 'ZIP' jest szeroko stosowany. To nie tylko kompresuje, ale także działa jako format kontenera do przesyłania strumieniowego dla wielu plików. Możesz mieć "plik" z powiązanymi informacjami jako pierwszy plik i używać identyfikatorów rzeczywistych plików jako nazw plików. Jeśli użyjesz trybu kompresji ZIP 'Store', będzie to faktycznie schemat' name, length, bytes' opisany w pytaniu. –

1

Jednym wyzwaniem, które widzę, jest to, że na podstawie liczby odsyłanych obrazów, rozmówca musi skorygować ich wartość limitu czasu. Gdyby to było w sklepie z książkami, może być dużo zdjęć wysłanych z powrotem.

Co zrobić, jeśli odesłałeś tylko adresy URL do każdego obrazu i pozostawiłeś je dzwoniącemu, aby uzyskać rzeczywisty obraz? Oznaczałoby to trochę więcej ruchu z wieloma połączeniami, ale osoba dzwoniąca otrzymywałaby informacje wcześniej niż później, a następnie otrzymywała obrazy na podstawie wymagań dzwoniącego.

Mógłbym się mylić, ale myślałem, że ideą odpoczynku jest identyfikacja każdego zasobu, a nie łączenie kilku obrazów i wywoływanie tego zasobu. Po prostu myśl ...

+0

Zgadzam się - prawdopodobnie nie jest to zbyt uciążliwe, żeby pakować podobne rzeczy, ale w rzeczywistości piszę też (tylko) aplikację, która będzie korzystać z tej usługi internetowej, więc myślę, że to jest w porządku. –

+1

Dobra uwaga na temat wartości limitu czasu, ale skoro również piszę klienta, mogę sobie z tym poradzić. (Prawdopodobnie będę prosił tylko o kilkanaście sztuk naraz). Sądzę, że dodatkowy ruch wymagany do wysłania 100 obrazów jest zbyt duży, by je znieść, więc pobieranie ich indywidualnie nie brzmi dla mnie dobrze. –

Powiązane problemy