2012-05-08 22 views
29

Quiero intentar utilizar la API web hacer una llamada a reposo pero quiero que la respuesta sea la imagen binaria real almacenada en una base de datos, no una cadena codificada JSON base64. Alguien tiene algunos consejos sobre esto?ASP .Net Web API descargando imágenes como binario

Update- Esto es lo que terminó de aplicación:

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

Creo que este artículo se hace una pregunta similar http://stackoverflow.com/questions/8340247/returning- an-image-from-a-restful-wcf-service –

Respuesta

28

puede establecer el contenido de la respuesta a un objeto 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

Marcó su respuesta como respuesta porque fue una respuesta directa a la pregunta y estuvo más cerca de lo que necesitaba. ¡Gracias por tomarse el tiempo para responder! – spaceagestereo

+0

Para obtener una solución sobre cómo devolver un archivo desde la API web, eche un vistazo al final de su propia respuesta en http://stackoverflow.com/a/14819168/179138 –

0

Esta tarea se logra mucho más fácilmente y sin usando WebAPI. Implementaría un HTTP handler personalizado para una extensión única, y devolvería la respuesta binaria allí. Lo mejor es que también puede modificar los encabezados de respuesta HTTP y el tipo de contenido, para que tenga control absoluto sobre lo que se devuelve.

Puede diseñar un patrón de URL (que define cómo sabe qué imagen debe devolver en función de su URL) y mantener esas URL en sus recursos de API. Una vez que la URL se devuelve en la respuesta de la API, puede ser solicitada directamente por el navegador y llegará a su controlador HTTP, devolviendo la imagen correcta.

Las imágenes son de contenido estático y tienen su propio rol en HTTP y HTML, sin necesidad de mezclarlas con el JSON que se usa cuando se trabaja con una API.

+10

Creo que OP quiere saber cómo hacerlo ** con webapi ** en lugar de cómo evitar webapi. – EBarr

+0

Correcto, conozco la ruta del controlador HTTP y la consideré, pero no quería que mi código se dividiera así. Gracias por tomarse el tiempo para responder sin embargo. – spaceagestereo

+0

Bueno, solo mis dos centavos.Siempre me ha parecido más fácil con los controladores HTTP. – Slavo

16

Si bien esto se marcó como respondido, no era exactamente lo que yo quería, así que seguí buscando. Ahora que he averiguado, esto es lo que tengo:

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

Por supuesto, eso es para conseguir una imagen a través de una URL. Si lo que desea es tomar una imagen fuera del servidor de archivos, me imagino que cambie esta línea:

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

Con esta:

using (Bitmap image = new Bitmap(myFilePath)) 

EDIT: No importa, esto es para MVC regular. para Web API, tengo esto:

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

Cual es bastante similar a lo que OP tiene.

+0

En mi caso, necesitaba la versión de API web. –

+0

¿Qué pasa con el objeto FileStream ... ¿Alguien sabe si el método predeterminado Dispose() en el httpResponseMessage destruirá apropiadamente el Stream? Nuestro escaneo de seguridad destaca esto como una fuga potencial de recursos no resuelta. – jessewolfe

1

Hice esto exactamente. Aquí está mi código:

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

Y luego en el cliente:

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