当磁盘上没有可用空间时,Image.Save不会抛出异常

4
我正在服务器上保存图像,并覆盖磁盘没有可用空间的情况。为了模拟这种情况,我创建了一个几乎没有空间的虚拟硬盘,并尝试在那里保存图像。
当我尝试保存图像时,我原本期望会收到异常:
using (var ms = new MemoryStream(myPictureStream))
using (Image image = Image.FromStream(ms))
{
    image.Save(fileName, ImageFormat.Jpeg);
}

但事实并非如此,没有异常被抛出。相反,保存了一个空文件,因此我无法意识到错误。 当尝试保存图像时,我希望能收到一些错误或能够预先预测错误而不会抛出异常。
我已经考虑了一些可能的解决方案:
- 我知道可以使用DriveInfo来检查驱动器上的可用空间,但我将没有驱动器号来检查生产环境中的驱动器,因此排除了此选项。 - 在保存图像后,我尝试使用Image.FromFile检索它,然后会引发OutOfMemoryException,但我知道在其他情况下也可能发生这种情况,并且我不确定这是否是检查磁盘没有可用空间的合法方式。
那么...为什么Image.Save()在没有可用空间时不抛出错误?有什么建议处理这种情况吗?
编辑 GetLastError 没有帮助(它是代码 0,成功),因此似乎处理此场景的最佳方法是将图像保存到临时 MemoryStream,然后将其写入文件,正如 @Eldar 和 @nvoigt 给出的答案所指出的那样。
这样做会抛出一个 IOException,您可以检查异常的 HResult,看看它是否是磁盘中没有足够的空闲空间的问题(请参见此答案:https://dev59.com/0Gox5IYBdhLWcg3wTina#9294382)。

1
阅读参考源代码,可知 .save 函数有时会调用 GDI Plus 保存图像(其他时候则使用 .net 文件 IO)。API 中的注释 (https://msdn.microsoft.com/en-us/library/windows/desktop/ms535407(v=vs.85).aspx) 指出,在保存时不会报告磁盘空间不足。 - pm100
1
也许你可以找出需要哪些函数调用和参数组合,来实现 .NET IO 中的保存调用。http://referencesource.microsoft.com/#System.Drawing/commonui/System/Drawing/Image.cs,5cd5db8a35628dd9,references - pm100
2个回答

6

Image.Save() 内部调用了一个 GDI 函数 GdipSaveImageToFile(),如果磁盘空间不足,则该函数不会失败。您可以尝试使用 GetLastError() 获取最后的 Win32 错误。

如果 GetLastError() 无法帮助您,我脑海中唯一的解决方案是将图像保存到临时的 MemoryStream 中,然后将结果流写入文件。


1

你需要自己处理流操作:

using (var ms = new MemoryStream(myPictureStream))
 using (Image image = Image.FromStream(ms))
  using(var jpg = new MemoryStream())
   using (var file = new FileStream(fileName, FileMode.Create, FileAccess.Write)) 
   {
      image.Save(jpg, ImageFormat.Jpeg);
      jpg.Seek(0, SeekOrigin.Begin);
      jpg.WriteTo(file);
   }    

感谢您的代码。我将@Eldar的答案标记为最佳答案,因为它已经给出了使用临时流然后保存到文件的想法,但是拥有代码也很好,非常有用的答案! - elbecita

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接