Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

System.ObjectDisposedException: Cannot access a disposed object. Object name: 'Cannot access a closed file.'

I am working on web API core and returning IActionResult. One of my API throws error while returning FileResult.

I get the following error.

System.ObjectDisposedException: Cannot access a disposed object. Object name: 'Cannot access a closed file.'.

My code is something like :

FileStream zipToOpen;

using (zipToOpen = new FileStream(Path.Combine(reportsPath, Guid.NewGuid().ToString()) + ".zip", FileMode.Create))
{
    using (ZipArchive zipArchive = new ZipArchive(zipToOpen, ZipArchiveMode.Create, true))
    {
        foreach (var document in documents)
        {
            string fileName = string.Empty;
            int index = document.Path.LastIndexOf("/");
            if (index != -1)
                fileName = document.Path.Substring(index + 1);
            zipArchive.CreateEntryFromFile(document.Path, fileName);                            
        }
    }

    //zipToOpen.Position = 0;
    return File(zipToOpen, "application/zip", "MyDocuments.zip");
}

Can anyone please help me what's the issue.

like image 604
Prakash Parmar Avatar asked Dec 14 '25 05:12

Prakash Parmar


2 Answers

As stated in another answer the file stream is being disposed of before the framework has had time to completed its functionality. That is because you are returning the stream in a using block which will dispose of the stream once the out of scope.

If there is no need for the archive to actually be saved/written to disk, consider building the archive in memory and return its stream.

//...

MemoryStream zipStream = new MemoryStream();
using (var zipArchive  = new ZipArchive(zipStream, ZipArchiveMode.Create, leaveOpen: true)) {
    foreach (var document in documents) {
        string fileName = document.Path;
        int index = fileName.LastIndexOf("/");
        if (index != -1)
            fileName = fileName.Substring(index + 1);
        zipArchive.CreateEntryFromFile(document.Path, fileName);
    } 
} // disposal of archive will force data to be written to memory stream.
zipStream.Position = 0; //reset memory stream position.
return File(zipStream, "application/zip", "MyDocuments.zip");

Note the memory stream will be disposed by the FileResult once it is finished with it.

like image 89
Nkosi Avatar answered Dec 16 '25 23:12

Nkosi


You're working with a stream, so until the stream is flushed or closed, you still need the component pieces like your ZipArchive. The problem is that you're returning the stream outside of the using statement where zipArchive sill exists. If you move your return inside that using block, you should be fine.

like image 44
Chris Pratt Avatar answered Dec 16 '25 23:12

Chris Pratt



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!