2012-05-08 34 views
29

Chcę spróbować użyć Web API nawiązać połączenie odpoczynku, ale chcę być odpowiedzią na rzeczywisty obraz binarny przechowywane w bazie danych, a nie base64 JSON zakodowany ciąg. Czy ktoś ma jakieś wskazówki na ten temat?ASP .Net Web API pobierania obrazów jako binarny

update To, co skończyło się realizacji:

HttpResponseMessage result = new HttpResponseMessage(HttpStatusCode.OK); 
result.Content = new StreamContent(new MemoryStream(profile.Avatar)); 
result.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream"); 
result.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment"); 
result.Content.Headers.ContentDisposition.FileName = "avatar.png"; 
return result; 
+0

Myślę, że ten artykuł zadaje podobne pytanie http://stackoverflow.com/questions/8340247/returning- an-image-od-a-spokojny-WCF usługi –

Odpowiedz

28

Można ustawić zawartość odpowiedzi do obiektu StreamContent:

 var fileStream = new FileStream(path, FileMode.Open); 

     var resp = new HttpResponseMessage() 
     { 
      Content = new StreamContent(fileStream) 
     }; 

     // Find the MIME type 
     string mimeType = _extensions[Path.GetExtension(path)]; 
     resp.Content.Headers.ContentType = new MediaTypeHeaderValue(mimeType); 
+2

Oznaczono jako swoje odpowiedzi, ponieważ była bezpośrednią odpowiedzią na pytanie i był najbliżej, co potrzebne. Dziękujemy za poświęcenie czasu na odpowiedź! – spaceagestereo

+0

Dla roztworu, w jaki sposób powrócić plik z API Web, spójrz na samym końcu własną odpowiedź na http://stackoverflow.com/a/14819168/179138 –

0

To zadanie jest dużo łatwo osiągnąć stosując bez WebAPI. Wdrożę niestandardowy HTTP handler dla unikalnego rozszerzenia i zwrócę tam odpowiedź binarną. Plus to, że możesz także zmodyfikować nagłówki HTTP Response i typ zawartości, dzięki czemu masz całkowitą kontrolę nad tym, co jest zwracane.

Można opracować wzorzec URL (określający, jak wiesz co zdjęcie aby powrócić na podstawie jego adresu URL) i zachować te adresy w zasobach API. Gdy URL zostanie zwrócony w odpowiedzi API, może zostać bezpośrednio zażądany przez przeglądarkę i dotrze do programu obsługi HTTP, zwracając poprawny obraz.

obrazy są statyczne i treść mają własną rolę w HTTP i HTML - nie ma potrzeby mieszać je z JSON, który jest używany podczas pracy z API.

+10

myślę PO chce wiedzieć, jak to zrobić ** z webapi ** zamiast jak uniknąć webapi. – EBarr

+0

Dobrze, znam trasę obsługi HTTP i rozważałem ją, ale nie chciałem, aby mój kod był tak podzielony. Dziękuję za poświęcenie czasu na odpowiedź. – spaceagestereo

+0

Cóż, tylko moje dwa centy.Zawsze znajdowałem to łatwiejsze z obsługą HTTP. – Slavo

16

Chociaż zostało to zaznaczone jako odpowiedź, nie było to dokładnie to, czego chciałem, więc wciąż szukałem. Teraz, kiedy to rozgryzłem, oto, co mam:

public FileContentResult GetFile(string id) 
{ 
    byte[] fileContents; 
    using (MemoryStream memoryStream = new MemoryStream()) 
    { 
     using (Bitmap image = new Bitmap(WebRequest.Create(myURL).GetResponse().GetResponseStream())) 
      image.Save(memoryStream, ImageFormat.Jpeg); 
     fileContents = memoryStream.ToArray(); 
    } 
    return new FileContentResult(fileContents, "image/jpg"); 
} 

To prawda, że ​​można uzyskać obraz za pośrednictwem adresu URL. Jeśli chcesz po prostu chwycić obraz wyłączania serwera plików, to bym sobie wyobrazić zastąpić ten wiersz:

using (Bitmap image = new Bitmap(WebRequest.Create(myURL).GetResponse().GetResponseStream())) 

z tym:

using (Bitmap image = new Bitmap(myFilePath)) 

EDIT: Nieważne, to jest do regularnego MVC. dla Web API, mam to:

public HttpResponseMessage Get(string id) 
{ 
    string fileName = string.Format("{0}.jpg", id); 
    if (!FileProvider.Exists(fileName)) 
     throw new HttpResponseException(HttpStatusCode.NotFound); 

    FileStream fileStream = FileProvider.Open(fileName); 
    HttpResponseMessage response = new HttpResponseMessage { Content = new StreamContent(fileStream) }; 
    response.Content.Headers.ContentType = new MediaTypeHeaderValue("image/jpg"); 
    response.Content.Headers.ContentLength = FileProvider.GetLength(fileName); 
    return response; 
} 

Co jest bardzo podobne do tego, co ma OP.

+0

W moim przypadku potrzebowałem wersji Web API. –

+0

Co z obiektem FileStream ... czy ktoś wie, czy metoda domyślna Dispose() na httpResponseMessage odpowiednio zniszczy Stream? Nasze skanowanie zabezpieczeń podkreśla to jako nierozwiązany potencjalny wyciek zasobów. – jessewolfe

1

Zrobiłem dokładnie to. Tu jest mój kodu:

if (!String.IsNullOrWhiteSpace(imageName)) 
       { 
        var savedFileName = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, Path.Combine(uploadPath, imageName)); 
        var image = System.Drawing.Image.FromFile(savedFileName); 

        if (ImageFormat.Jpeg.Equals(image.RawFormat)) 
        { 
         // JPEG 
         using(var memoryStream = new MemoryStream()) 
         { 
          image.Save(memoryStream, ImageFormat.Jpeg); 

          var result = new HttpResponseMessage(HttpStatusCode.OK) 
           { 
            Content = new ByteArrayContent(memoryStream.ToArray()) 
           }; 

          result.Content.Headers.ContentType = new MediaTypeHeaderValue("image/jpeg"); 
          result.Content.Headers.ContentLength = memoryStream.Length; 

          return result; 
         } 
        } 
        else if (ImageFormat.Png.Equals(image.RawFormat)) 
        { 
         // PNG 
         using (var memoryStream = new MemoryStream()) 
         { 
          image.Save(memoryStream, ImageFormat.Png); 

          var result = new HttpResponseMessage(HttpStatusCode.OK) 
          { 
           Content = new ByteArrayContent(memoryStream.ToArray()) 
          }; 

          result.Content.Headers.ContentType = new MediaTypeHeaderValue("image/png"); 
          result.Content.Headers.ContentLength = memoryStream.Length; 

          return result; 
         } 
        } 
        else if (ImageFormat.Gif.Equals(image.RawFormat)) 
        { 
         // GIF 
         using (var memoryStream = new MemoryStream()) 
         { 
          image.Save(memoryStream, ImageFormat.Gif); 

          var result = new HttpResponseMessage(HttpStatusCode.OK) 
          { 
           Content = new ByteArrayContent(memoryStream.ToArray()) 
          }; 

          result.Content.Headers.ContentType = new MediaTypeHeaderValue("image/gif"); 
          result.Content.Headers.ContentLength = memoryStream.Length; 

          return result; 
         } 
        } 
       } 

A potem na kliencie:

    var client = new HttpClient(); 
        var imageName = product.ImageUrl.Replace("~/Uploads/", ""); 
       var path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, 
             Properties.Settings.Default.DeviceMediaPath + "\\" + imageName); 

       var response = 
        client.GetAsync(apiUrl + "/Image?apiLoginId=" + apiLoginId + "&authorizationToken=" + authToken + 
            "&imageName=" + product.ImageUrl.Replace("~/Uploads/","")).Result; 

       if (response.IsSuccessStatusCode) 
       { 
        var data = response.Content.ReadAsByteArrayAsync().Result; 
        using (var ms = new MemoryStream(data)) 
        { 
         using (var fs = File.Create(path)) 
         { 
          ms.CopyTo(fs); 
         } 
        } 

        result = true; 
       } 
       else 
       { 
        result = false; 
        break; 
       } 
Powiązane problemy