C#调用方法后InputStream为空,二次调用失效问题求助
问题分析与解决方案
这个问题的核心原因是原始InputStream的位置指针在第一次处理后已经移动到了流的末尾,而且很多情况下(比如ASP.NET上传文件的HttpPostedFile.InputStream)这类流是不支持重新定位(Seek)操作的——哪怕你在方法里写了inputStream.Position = 0,实际也不会生效,导致第二次调用时流已经没有可读内容了。
第一次调用正常是因为初始时流的位置在起始处,能被正常读取处理;但第一次处理完成后,流的指针已经走到了末尾,第二次调用时重置位置的操作失效,自然就会出现“流为空”的情况。
解决方案:提前复制流到可Seek的MemoryStream
最稳妥的办法是在第一次使用原始流之前,把它完整复制到一个MemoryStream中(MemoryStream完全支持Seek操作),之后所有的处理都基于这个副本进行:
// 先把原始的file.InputStream完整复制到MemoryStream,保存一份可重复读取的副本 using var reusableStream = new MemoryStream(); file.InputStream.CopyTo(reusableStream); // 第一次调用前重置流位置到起始处 reusableStream.Position = 0; var imageOutputStream = ConvertImageAsStream(reusableStream, imageWidth, imageHeight); // 第二次调用前再次重置位置 reusableStream.Position = 0; var thumbnailOutputStream = ConvertImageAsStream(reusableStream, thumbnailWidth, thumbnailHeight);
可选优化:让方法兼容不可Seek的流
如果你想让ConvertImageAsStream方法本身更健壮,能自动处理不可Seek的流,可以在方法内部先做判断,必要时复制流:
public static MemoryStream ConvertImageAsStream(Stream inputStream, int widthPercentage, int heightPercentage) { var outputStream = new MemoryStream(); // 准备一个可操作的工作流:如果输入流不支持Seek,先复制到MemoryStream Stream workingStream; if (inputStream.CanSeek) { workingStream = inputStream; workingStream.Position = 0; } else { workingStream = new MemoryStream(); inputStream.CopyTo(workingStream); workingStream.Position = 0; } if (workingStream.Length > 0) { var imageJob = new ImageJob(workingStream, outputStream, imageResizeSettings); imageJob.Instructions.AutoRotate = true; imageJob.Build(); } // 重置输出流位置,方便调用方直接读取 outputStream.Position = 0; return outputStream; }
这样修改后,不管传入的是哪种类型的流,方法都能正确处理,而且对于支持Seek的流,也不会额外复制,能节省内存开销。
内容的提问来源于stack exchange,提问作者Tom
相关产品推荐
相关产品推荐

