Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

No exception thrown on Image.Save when no free space on disk

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).

like image 570
elbecita Avatar asked Mar 13 '23 14:03

elbecita


2 Answers

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.

like image 62
Eldar Dordzhiev Avatar answered Mar 30 '23 00:03

Eldar Dordzhiev


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);
   }    
like image 33
nvoigt Avatar answered Mar 30 '23 01:03

nvoigt