Czy istnieje zalecany sposób zwracania obrazu przy użyciu interfejsu API sieci Web ASP.NET

86

Jaki jest najlepszy sposób na zwrócenie obrazu z 2 parametrami (x i y dla zmiany rozmiaru).

Na przykład

~/api/image12345/200/200

Zwróci 200 na 200 jpg / png / lub gif

Czy powinienem zwrócić System.Drawing.Imageobiekt, czy ręcznie zdefiniować HTTPReponseMessage.Content?

Max Alexander
źródło
Sprawdź moją odpowiedź tutaj: stackoverflow.com/a/20888749/64334
Ronnie Overby

Odpowiedzi:

147

Nie powinieneś zwracać a System.Drawing.Image, chyba że dodasz również program formatujący, który wie, jak przekonwertować to na odpowiednie bajty, nie serializuje się jako bajty obrazu, jak można się spodziewać.

Jednym z możliwych rozwiązań jest zwrócenie pliku HttpResponseMessagez obrazem przechowywanym w jego treści (jak pokazano poniżej). Pamiętaj, że jeśli potrzebujesz adresu URL, który pokazałeś w pytaniu, potrzebujesz trasy, która odwzorowuje parametry {imageName}, {width} i {height}.

public HttpResponseMessage Get(string imageName, int width, int height)
{
    Image img = GetImage(imageName, width, height);
    using(MemoryStream ms = new MemoryStream())
    {
        img.Save(ms, System.Drawing.Imaging.ImageFormat.Png);

        HttpResponseMessage result = new HttpResponseMessage(HttpStatusCode.OK);
        result.Content = new ByteArrayContent(ms.ToArray());
        result.Content.Headers.ContentType = new MediaTypeHeaderValue("image/png");

        return result;
    }
}

Ale znowu, jeśli robisz to w wielu miejscach, skorzystanie z trasy formatera może być sposobem „zalecanym”. Jak prawie wszystko w programowaniu, odpowiedź będzie zależeć od twojego scenariusza.

carlosfigueira
źródło
Czy obraz powinien być również używany?
dibs487
Gdzie jest GetImagemetoda?
Yoda
1
@Yoda to metoda w Twojej implementacji, która zwróci obraz, który należy przesłać z powrotem do klienta.
carlosfigueira
Jeśli zwracasz plik z dysku twardego, myślę, że lepszą wydajność byłoby użycie FileStream, w ten sposób (patrz zaakceptowana odpowiedź w tym pytaniu): stackoverflow.com/questions/11125535/ ...
John Gilmer
19

Obrazy są ciężkie. ASP.NET WebForms, HttpHandlers, MVC i Web API wykonują absolutnie straszną robotę obsługującą pliki statyczne. Usługi IIS wykonują bardzo dobrą robotę - często 20-100 razy wydajniej.

Jeśli chcesz uzyskać dobrą wydajność, przeprowadź ponowne zapisywanie adresu URL najpóźniej podczas PostAuthorizeRequest, aby usługi IIS mogły odebrać i udostępnić plik. Tak, oznacza to obsługę zdarzeń na poziomie HttpModule.

[Uwaga: jestem autorem następującego artykułu i projektu open source]

Jeśli robisz coś dynamicznego z obrazami, zapoznaj się z tym artykułem na temat pułapek przetwarzania obrazu, których należy unikać , i rozważ przyjrzenie się ImageResizer . Ma doskonałe buforowanie dysku (które wykorzystuje statyczną obsługę plików IIS) i jest łatwe do podłączenia do dowolnego rodzaju generowania obrazu. Ma również opcjonalne powiązania dla AForge, FreeImage i WIC, jeśli chcesz przejść zaawansowany.

Lilith River
źródło
2
Używam ImageResizera w moim projekcie i jestem bardzo zadowolony z jego działania - plus ode mnie. Jedynym problemem jest to, że część dokumentacji wymaga aktualizacji.
Jon L,