El uso de WebClient para obtener Remoto Produce Imágenes Granuladas de GIFs y no Puede Manejar el PNG BMP

StackOverflow https://stackoverflow.com/questions/499210

  •  20-08-2019
  •  | 
  •  

Pregunta

Saludos!

Estoy creando una web en forma de prototipo (ImageLaoder.aspx) que devolverá una imagen para que pueda ser utilizado como este simple ejemplo, otras Formas de Web/páginas web:

<img src="http://www.mydomain.com/ImageLoader.aspx?i=http://images.mydomain.com/img/a.jpg" />

Hasta el momento, se carga en Jpg sin problemas, sin embargo los GIFs de la mirada "grano" en comparación con el orignals y Bmp y Png resultado en la siguiente excepción:

Sistema.En tiempo de ejecución.InteropServices.ExternalException:Un error genérico que se produjo en GDI+

Mi código por lo tanto ahora se ve como este:

protected void Page_Load(object sender, EventArgs e)
{
    string l_filePath = Request.QueryString["i"];

    System.Drawing.Image l_image = GetImage(l_filePath);
    if (l_image != null)
    {
        System.Drawing.Imaging.ImageFormat l_imageFormat = DetermineImageFormat(l_filePath);
        WriteImageAsReponse(l_image, l_imageFormat);
    }
}

private System.Drawing.Image GetImage(string filePath)
{
    WebClient l_WebClient = new WebClient();
    byte[] l_imageBytes = l_WebClient.DownloadData(filePath);

    System.Drawing.Image l_image = null;
    using (MemoryStream l_MemStream = new MemoryStream(l_imageBytes, 0, l_imageBytes.Length))
    {
        l_MemStream.Write(l_imageBytes, 0, l_imageBytes.Length);
        l_image = System.Drawing.Image.FromStream(l_MemStream, true);
        l_MemStream.Close();
    }

    return l_image;
}

private System.Drawing.Imaging.ImageFormat DetermineImageFormat(string filePath)
{
    if (filePath.EndsWith(".jpg", StringComparison.OrdinalIgnoreCase))
        return System.Drawing.Imaging.ImageFormat.Jpeg;
    else if (filePath.EndsWith(".gif", StringComparison.OrdinalIgnoreCase))
        return System.Drawing.Imaging.ImageFormat.Gif;
    else if (filePath.EndsWith(".png", StringComparison.OrdinalIgnoreCase))
        return System.Drawing.Imaging.ImageFormat.Png;
    else
        return System.Drawing.Imaging.ImageFormat.Bmp;
}

private void WriteImageAsReponse(System.Drawing.Image image, System.Drawing.Imaging.ImageFormat imageFormat)
{
    if (image == null)
        return;

    System.Drawing.Bitmap l_outputBitMap = new Bitmap(image);

    if (imageFormat == System.Drawing.Imaging.ImageFormat.Jpeg)
        Response.ContentType = "image/jpg";
    else if (imageFormat == System.Drawing.Imaging.ImageFormat.Gif)
        Response.ContentType = "image/gif";
    else if (imageFormat == System.Drawing.Imaging.ImageFormat.Png)
        Response.ContentType = "image/png";
    else
        Response.ContentType = "image/bmp";

    l_outputBitMap.Save(Response.OutputStream, imageFormat);
}

Alguna idea de por qué los GIFs son granulada y Png y Bmp causa excepciones?

¿Fue útil?

Solución

Algunos puntos acerca de su método GetImage:

  • Cuando el uso de la Imagen.FromStream no debe cerrar (o desechar) el flujo de
  • Si usted está llamando a Disponer de un flujo (con la instrucción de uso) no es necesario llamar a Close
  • Usted está escribiendo a la corriente, pero luego no "rebobinar" para l_image en realidad no obtener ningún dato tan lejos como puedo ver (a menos que la Imagen.FromStream restablece la posición del mismo).(Podría ser que el archivo gif/jpg decodificadores de rebobinado de la corriente, pero bmp/png no, de ahí el error.)
  • Por qué no simplemente usar el MemoryStream constructor que toma una matriz de bytes?

En resumen, yo creo que su método GetImage puede ser sustituida por:

private Image GetImage(string filePath)
{
    WebClient l_WebClient = new WebClient();
    byte[] l_imageBytes = l_WebClient.DownloadData(filePath);
    MemoryStream l_stream = new MemoryStream(l_imageBytes);
    return Image.FromStream(l_stream);
}

Ahora, lo que es más importante - ¿por qué la carga de la imagen en todo?¿Por qué no acaba de servir el archivo en sí como respuesta, estableciendo el tipo de contenido, como ya está haciendo - o, posiblemente, sólo basada en la extensión?En otras palabras, todo el código sería:

protected void Page_Load(object sender, EventArgs e)
{
    string filePath = Request.QueryString["i"];
    string extension = l_filePath.Substring(l_filePath.LastIndexOf('.') + 1);
    Response.ContentType = "image/" + extension;
    byte[] data = new WebClient.DownloadData(filePath);
    Response.OutputStream.Write(data, 0, data.Length);
    Response.End();
}

Un poco más de control de errores (incluyendo "es esta una extensión razonable?") sería bueno, pero aparte de eso me parece bien.La única ventaja de que en realidad la carga de la imagen que se obtiene es que para validar que realmente es una imagen en lugar de un virus o algo por el estilo.

EDITAR:Acaba de salir de interés, ¿usted tiene una buena razón por la que había quiero las solicitudes de imágenes a través de su servidor?¿Por qué el autor de la página web de escribir:

<img src="http://www.mydomain.com/ImageLoader.aspx?i=http://images.mydomain.com/img/a.jpg" />

en lugar de

<img src="http://images.mydomain.com/img/a.jpg" />

Allí son algunas razones por las que podría ser útil, pero en muchos casos es sólo un desperdicio.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top