I think this is pretty simple. My program will create an Excel file on the server using Automation. After that, I want to force the user to choose whether or not to download it, then, regardless of the choice, delete the file so it won't just take up space. Any ideas on how I could accomplish this?
You could read the file into an input buffer then delete the file and send the buffer to the user instead of the actual file.
It's hard to know when the user has actually finished downloading the file, and you don't want to delete it before doing so, therefore my advice is to delete files older than a certain amount of time, for example > 24 hours.
It's hard to determine if the user has finished downloading the file because the browser doesn't transmit this information, and other than packet sniffing the network data and configuring in detail your webserver to manage its open connections, and actually believing it won't make errors, there's no simple way.
It also depends how you're reading the file and its actual size, for example going line by line to output to the browser will save memory, but it'll make the code dependant on the file's existence, while reading the file's content to some kind of buffer will allow the webserver to well, serve it, but depending on the number of visitors, the file size, and average download speed, you might have at any time a webserver with dozens of GB files in memory.
It's just easier to have enough space for a few days worth of data and delete files every now and then.
A really nice way, is in your global.asax
I think SO uses something similar, although I forget for what... (Am sure I stole this code off them)
private static CacheItemRemovedCallback OnCacheRemove = null;
private void AddTask(string name, int seconds)
{
OnCacheRemove = new CacheItemRemovedCallback(CacheItemRemoved);
HttpRuntime.Cache.Insert(name, seconds, null, DateTime.Now.AddSeconds(seconds), Cache.NoSlidingExpiration, CacheItemPriority.NotRemovable, OnCacheRemove);
}
void Application_Start(object sender, EventArgs e)
{
// Code that runs on application startup
// delete old spreadsheets every hour
AddTask("DeleteDayOldSpreadsheets", 3600);
}
public void CacheItemRemoved(string k, object v, CacheItemRemovedReason r)
{
// do stuff here
switch (k)
{
case "DeleteDayOldSpreadsheets":
// TODO: add your magic DELETE OLD SPREADSHEET code here
break;
default:
break;
}
// re-add our task so it recurs
AddTask(k, Convert.ToInt32(v));
}
As stated in Microsoft KB 257757, Microsoft recommends against using automation on a server:
"Microsoft does not currently recommend, and does not support, Automation of Microsoft Office applications from any unattended, non-interactive client application or component (including ASP, ASP.NET, DCOM, and NT Services), because Office may exhibit unstable behavior and/or deadlock when Office is run in this environment."
SpreadsheetGear for .NET and other 3rd party libraries can do it and they will be faster as well as more reliable. SpreadsheetGear supports writing directly to the output stream so you have no need to create a temporary file on disk - giving better performance and no worry about cleaning up the left-over files.
You can see ASP.NET Excel Reporting samples with C# and VB source here and download a free trial here if you want to try it out for yourself.
Disclaimer: I own SpreadsheetGear LLC