使用WebClient获取远程图像会产生粒状GIF,无法处理PNG + BMP

问候!

我正在创建一个Web表单原型(ImageLaoder.aspx),它将返回一个图像,以便它可以像其他Web表单/网页这样的简单示例一样使用:

 

到目前为止,它加载JPG没有问题,但是与原始数据相比,GIF看起来“颗粒状”,而BMP和PNG导致以下exception:

System.Runtime.InteropServices.ExternalException:GDI +中发生一般错误

到目前为止我的代码看起来像这样:

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

任何想法为什么GIF是颗粒状的,PNG和BMP导致exception?

关于GetImage方法的几点:

  • 使用Image.FromStream时,不应关闭(或处置)流
  • 如果您在流上调用Dispose(使用using语句),则无需调用Close
  • 你正在写入流,但后来没有“倒带”,所以l_image实际上并没有我能看到的任何数据(除非Image.FromStream重置位置本身)。 (可能是gif / jpg解码器倒回流但是bmp / png没有,因此错误。)
  • 为什么不使用带有字节数组的MemoryStream构造函数?

简而言之,我相信您的GetImage方法可以替换为:

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

现在,更重要的是 – 为什么要加载图像? 为什么不直接将文件本身作为响应提供,设置内容类型就像你已经在做的那样 – 或者可能只是基于扩展名? 换句话说,您的所有代码都将成为:

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

更多的error handling(包括“这是一个合理的扩展吗?”)会很好,但除此之外我觉得没关系。 实际加载图像的唯一好处是,您可以validation它确实图像而不是病毒或类似的东西。

编辑:只是出于兴趣,你有充分的理由为什么你想要图像请求通过你的服务器? 为什么网页作者会写:

  

代替

  

有一些原因可能会有用,但在许多情况下,这只是一种浪费。