C#从Stream生成缩略图时遭遇ArgumentException及流已关闭异常的技术求助
问题排查与解决方案
看起来你碰到了两个关联的流处理问题,咱们一步步拆解解决:
1. 先解决「无法访问已关闭的流」异常
这个是最直接的问题——你的ResizeImageToThumbnail方法里用了using var thumbnailStream = new MemoryStream();,using关键字会在方法执行完后自动释放(关闭)这个内存流,所以当AttachThumb方法拿到返回值时,流已经处于关闭状态了。
修复方案:
去掉using关键字,让调用方来管理流的生命周期,同时别忘了把流指针重置到开头(否则读取会从流的末尾开始):
public Stream ResizeImageToThumbnail(Stream imageStream, int width) { var image = Image.FromStream(imageStream); var height = (width * image.Height) / image.Width; var thumbnail = image.GetThumbnailImage(width, height, null, IntPtr.Zero); var thumbnailStream = new MemoryStream(); thumbnail.Save(thumbnailStream, ImageFormat.Jpeg); thumbnailStream.Position = 0; // 重置指针到流的起始位置 return thumbnailStream; }
然后在AttachThumb方法里,用using包裹返回的流,确保使用完后释放:
public void AttachThumb(Guid id, Stream imageStream, string imageName) { Post post = GetPost(id); using var thumbnailStream = ResizeImageToThumbnail(imageStream, 640); ObjectId imageId = _gridFS.UploadFromStream(imageName, thumbnailStream); post.ImagesThumbs.Add(imageId.ToString()); var filter = Builders<Post>.Filter.Eq(x => x.Id, id); var update = Builders<Post>.Update.Set("ImagesThumbs", post.ImagesThumbs); _posts.UpdateOne(filter, update); }
2. 再解决Image.FromStream的「参数无效」异常
这个异常通常和流的状态有关,结合你的循环代码,大概率是这两个原因:
- 你直接用
item.OpenReadStream()返回的流,在调用AttachImage后,流的位置可能没正确重置到开头,导致Image.FromStream读取的是空内容; System.Drawing.Image.FromStream会保留对流的引用,如果流在后续操作中被意外关闭,也会触发这个异常。
修复方案:
推荐把IFormFile的内容复制到独立的MemoryStream中,避免原流的位置和生命周期问题:
foreach (var item in model.UploadedImages) //item = IFormFile,前端仅允许上传图片 { using var ms = new MemoryStream(); // 先把上传文件的内容复制到新的内存流 await item.CopyToAsync(ms); ms.Position = 0; _service.AttachImage(newId, ms, item.FileName); ms.Position = 0; // 重置指针到开头,供后续缩略图生成使用 _service.AttachThumb(newId, ms, item.FileName); }
另外,记得给Image和Thumbnail对象加上using,避免GDI+资源泄漏:
public Stream ResizeImageToThumbnail(Stream imageStream, int width) { using var image = Image.FromStream(imageStream); var height = (width * image.Height) / image.Width; using var thumbnail = image.GetThumbnailImage(width, height, null, IntPtr.Zero); var thumbnailStream = new MemoryStream(); thumbnail.Save(thumbnailStream, ImageFormat.Jpeg); thumbnailStream.Position = 0; return thumbnailStream; }
额外优化建议
System.Drawing在ASP.NET Core跨平台场景下有不少兼容性问题,推荐换成更现代的图片处理库ImageSharp(安装SixLabors.ImageSharp NuGet包),它的流处理更友好,异常信息也更清晰:
using SixLabors.ImageSharp; using SixLabors.ImageSharp.Processing; using SixLabors.ImageSharp.Formats.Jpeg; public Stream ResizeImageToThumbnail(Stream imageStream, int width) { using var image = Image.Load(imageStream); var height = (width * image.Height) / image.Width; image.Mutate(x => x.Resize(width, height)); var thumbnailStream = new MemoryStream(); image.Save(thumbnailStream, new JpegEncoder()); thumbnailStream.Position = 0; return thumbnailStream; }
内容的提问来源于stack exchange,提问作者user15896272
相关产品推荐
相关产品推荐

