4

I am saving images on the server and I am covering the scenario where the disk has no available free space. To simulate that, I created an almost-no-space virtual hard drive and I am trying to save the images there.

I was expecting to receive an exception when trying to save the image, with:

using (var ms = new MemoryStream(myPictureStream))
using (Image image = Image.FromStream(ms))
{
    image.Save(fileName, ImageFormat.Jpeg);
}

But that is not the case, there is no exception thrown. Instead, an empty file is saved, so I can not be aware of the error. I would like to receive some error when trying to save the image, or being able to anticipate the error before an exception is thrown.

I already considered some possible solutions:

  • I know I can check the available free space on a drive with DriveInfo, but I will not have the drive letter to check that on production, so this option is discarded.
  • After saving the image, I try to retrieve it with Image.FromFile and then an OutOfMemoryException is thrown, but I know that this can happen in other scenarios, and I am not sure if this is a legitimate way of checking that the disk has no free space.

So... Any idea why Image.Save() does not throw errors when no free space available? Any suggestion on how to handle this scenario?

EDIT

GetLastError does not help (it is code 0, success), so it seems that the best way to handle this scenario is saving the image to a temporal MemoryStream and then writing it into a file, as pointed out by answers given by @Eldar and @nvoigt.

Doing it this way, a IOException is thrown, and you can check the HResult of the exception to see if it is a not-enough-free-space-in-disk easy (see this answer: https://stackoverflow.com/a/9294382/4067893).

Community
  • 1
  • 1
elbecita
  • 2,616
  • 19
  • 28
  • 1
    reading the reference source the .save function sometimes calls GDI plus to save the image (other times it uses .net file io). There is a comment in the API used https://msdn.microsoft.com/en-us/library/windows/desktop/ms535407(v=vs.85).aspx saying that when saving the API doesnt report out of disk space – pm100 Apr 15 '16 at 15:10
  • 1
    maybe you can work out what combination of calls / params / .. are needed to make save call .net io. http://referencesource.microsoft.com/#System.Drawing/commonui/System/Drawing/Image.cs,5cd5db8a35628dd9,references – pm100 Apr 15 '16 at 15:13

2 Answers2

6

Image.Save() internally calls a GDI function GdipSaveImageToFile() that doesn't fail if the drive space is insufficient. You may give a try to GetLastError() to get the last Win32 error.

If GetLastError() doesn't help, the only solution that comes up in my mind is saving the image to a temporal MemoryStream, then writing the resulting stream into a file.

Eldar Dordzhiev
  • 5,105
  • 2
  • 22
  • 26
1

You will need to do the stream handling yourself:

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);
   }    
nvoigt
  • 75,013
  • 26
  • 93
  • 142
  • Thanks for the code. I marked @Eldar answer as the good one since it already gives the idea of using the temporal stream and then saving into a file, but it is good to have the code, useful answer! – elbecita Apr 18 '16 at 08:04