2016-04-21 10 views
6

Robię Web Api i potrzebuję zwrócić wiele obrazów do klienta. Obecnie używam łańcucha Base64 dla każdego obrazu, ale powoduje to, że każde żądanie trwa zbyt długo. Czy istnieje lepszy, bardziej skuteczny sposób zwracania obrazów?Powracanie obrazów z WebApi

Jest to kod używam:

Kontroler:

public LearningUnits GetLearningUnits([FromODataUri]Guid key) 
    { 
     var record = db.LearningUnits.SingleOrDefault(inst => inst.LearningUnitId == key); 

     record.ImageURLPath = ImageHandler.ImageToByteArrayFromFilePath(record.ImageURLPath); 

     return record; 
    } 

ImageToByteArray Metoda:

public static string ImageToByteArrayFromFilePath(string imagefilePath) 
    { 
     byte[] imageArray = File.ReadAllBytes(imagefilePath); 

     string baseImage = Convert.ToBase64String(imageArray); 

     return baseImage; 
    } 
+0

Ile takie obrazy są tam w sumie? –

+5

Dlaczego nie możesz zwrócić adresu URL w swoim modelu, a następnie klient będzie wysuwał kolejne żądania uzyskania plików binarnych obrazów? – tenbits

+0

Zależy od ilości rekordów w bazie danych. Każdy rekord ma obraz. Może to być od 1 do 1000. –

Odpowiedz

0

Rozwiązaniem jest użycie formaterów formatów multimedialnych, więc gdy interfejs Web API zostanie zapytany o określony typ, otrzymasz aktualny strumień binarny określonego typu.

http://www.asp.net/web-api/overview/formats-and-model-binding/media-formatters

to średnia relaksującego szwu; masz ten sam adres URL, ale gdy chcesz uzyskać rekord JSON dla danych, zaakceptuj-type: application/json, ale zmieniasz typ żądania MIME na image/png lub coś podobnego, kiedy chcesz tego typu mediów.

Więcej można znaleźć tutaj: How to provide custom mediatype formats for OData Api

OData również pośrednio wspiera go tutaj: https://msdn.microsoft.com/en-us/library/system.web.http.odata.formatter.odatamediatypeformatter(v=vs.118).aspx

+1

Nie jest dobrym pomysłem zwracanie różnych danych dla jednego punktu końcowego. MediaFormattery są dobre tylko dla różnych formatów ** tych samych ** danych. W przeciwnym razie fiołek narusza zasadę jednej odpowiedzialności i nie jest powszechnym wzorcem REST. Z pewnością możesz zwrócić obraz zamiast json, ale tylko wtedy, gdy obraz w pełni reprezentuje dane. – tenbits

+0

Ja z szacunkiem się nie zgadzam; jeśli obraz jest reprezentatywny dla danego podmiotu, można argumentować, że jest to typ zawartości tego konkretnego podmiotu. Jeśli istnieje tylko jedna wizualizacja obrazu dla encji danych, to wizualizacja obrazu jest odpowiednia, nawet jeśli obraz nie jest pełną reprezentacją całego obiektu (który w każdym razie może zawierać telemetrię itp. Z czegoś takiego jak OData). Gdybyśmy przyjęli logikę do pełnego wniosku, nie powinniśmy nawet reprezentować obiektu jako aplikacji/json lub application/xml, ponieważ różni się ona zasadniczo od natywnej formy danych. –

+0

Nazewnictwo 'MediaType' **' Formatter' ** mówi, że tylko formatator różni się dla encji. Oczywiście, serializując dane do określonego typu, może istnieć więcej lub mniej informacji. Rozważ punkt końcowy '[get]/api/v1/blog/123', gdy zażądasz go z' accept: image/png' nie wystarczy, aby zwrócić tylko główny obraz posta na blogu, ale byłoby ok, jeśli wygeneruj obraz z tytułem nad nim. Jeśli ktoś chce zwrócić tylko wartość właściwości, taką jak 'ImageURLPath', wówczas należy zdefiniować jawny punkt końcowy:' [get]/api/v1/blog/123/image'. – tenbits

1

Jeśli punkt końcowy zwraca JSON, to nie ma innego wyjścia, poza base64 , jak osadzić pliki binarne w odpowiedzi. Ale jest to zdecydowanie zły pomysł ze względu na problemy z wydajnością. Może dla niektórych ikon będzie dobrze, ale dla większych obrazów nie jest odpowiedni.

Najlepszym rozwiązaniem jest tutaj zwrócenie adresu URL do obrazu. Klient zażąda dalszego pozyskania surowych bajtów dla obrazu.

Warto również wspomnieć, że adres URL obrazu może być nie tylko ścieżką do pliku statycznego, ale także ścieżką do punktu końcowego webapi, który na przykład pobiera bajty obrazu według identyfikatora zasobu i wysyła klienta powrót binarny, a nie ciąg jsonów.

+0

Postanowiłem wybrać tę trasę. Nie znalazłem lepszych opcji i byłoby to najskuteczniejsze. –