byte[]转Image失败排查:数据库图片读取转换异常
问题分析与解决方案
1. ViewBag使用错误触发空引用异常
你现在调用ViewBag.Add(ScreenshotImagesFullsize);的方式完全错了!ViewBag本质是动态的键值对集合,它的Add方法需要传入键和值,而不是直接丢一个列表进去。正确的做法是给ViewBag赋值一个命名属性,比如:
ViewBag.ScreenshotImagesFullsize = ScreenshotImagesFullsize;
原来的写法会让ViewBag无法识别你要传递的数据,直接导致"Cannot perform runtime binding on a null reference"这个错误。
2. MemoryStream提前释放导致Image失效
这是你遇到的核心问题!你在创建Image后立刻调用memstr.Dispose();,但Image.FromStream生成的Image对象不会立即把流里的图片数据复制到自身内存,它会保留对源流的引用。当你提前释放流之后,Image就失去了数据来源——这就是为什么禁用JIT优化后能看到height、width这些元数据(读取流时缓存的),但实际像素数据显示为null的原因。
两种修复方案:
方案一:让Image关联流的生命周期
直接去掉memstr.Dispose();这行代码,因为当Image对象被垃圾回收时,会自动释放关联的流。修改后的转换方法:
private List<Image> ConvertByteArraysToImages(List<byte[]> byteDataList) { List<Image> retVal = new List<Image>(); int counter = 0; foreach (byte[] byteData in byteDataList) { MemoryStream memstr = new MemoryStream(byteData); Image img = Image.FromStream(memstr); retVal.Add(img); // 注释掉Dispose,让Image管理流的生命周期 // memstr.Dispose(); System.IO.File.WriteAllBytes(String.Format(@"C:\dev\test{0}.png", counter), byteData); counter++; } return retVal; }
方案二:转成Bitmap复制流数据(更安全)
Bitmap对象会把流中的图片数据完整复制到自身内存,这样就可以安全释放流了,还能避免内存泄漏风险:
private List<Image> ConvertByteArraysToImages(List<byte[]> byteDataList) { List<Image> retVal = new List<Image>(); int counter = 0; foreach (byte[] byteData in byteDataList) { using (MemoryStream memstr = new MemoryStream(byteData)) { // 用Bitmap包装,把流数据复制到内存 Bitmap bmp = new Bitmap(Image.FromStream(memstr)); retVal.Add(bmp); } // using块结束自动释放流 System.IO.File.WriteAllBytes(String.Format(@"C:\dev\test{0}.png", counter), byteData); counter++; } return retVal; }
额外提醒:Image无法直接在视图显示
就算你解决了上面的问题,直接把Image对象传给ViewBag也没法在HTML里显示——浏览器需要的是图片URL或者Base64编码。你可以在控制器里把Image转成Base64字符串再传递:
List<string> imageBase64List = new List<string>(); foreach(var img in ScreenshotImagesFullsize) { using(MemoryStream ms = new MemoryStream()) { img.Save(ms, System.Drawing.Imaging.ImageFormat.Png); byte[] imageBytes = ms.ToArray(); string base64String = Convert.ToBase64String(imageBytes); imageBase64List.Add($"data:image/png;base64,{base64String}"); } } ViewBag.ScreenshotBase64 = imageBase64List;
然后在视图里用<img src="@item" />就能直接显示图片了。
内容的提问来源于stack exchange,提问作者user602095
相关产品推荐
相关产品推荐

