3

I'm trying to implement what I'd call a "one time cache" for specific files in my ASP.NET 3.5 site. Upon request, the file is downloaded from a remote file server onto the web server, then served up by my page. The problem arises when I go to delete it. If I delete the file in the OnUnload method, the client doesn't have time to retrieve it. Is there some way of detecting the download of a file and deleting it immediately after it is first accessed? My code is like this:

    private bool _deleteFlag = false;
    private string _deleteFile = string.Empty;

    protected void Page_Load(object sender, EventArgs e) {
        if (!string.IsNullOrEmpty(Request.QueryString["file"])) {
            _deleteFlag = Request.QueryString["file"].Contains(@"cache/");
            _deleteFile = Request.QueryString["file"];
        }
    }

    protected override void OnUnload(EventArgs e) {
        if (_deleteFlag) {
            // Can't delete here; the client is still trying to retrieve it.
            System.IO.File.Delete(Server.MapPath(_deleteFile));
        }
        base.OnUnload(e);
    }

I'm leaning towards writing an IHttpHandler that overrides the file request, but that feels like overkill.

Stephen Collins
  • 3,523
  • 8
  • 40
  • 61
  • If you have access to IIS you can try this [SO link][1] [1]: http://stackoverflow.com/questions/2195266/how-to-configure-static-content-cache-per-folder-and-extension-in-iis7 – karthickj25 Jul 15 '14 at 12:45
  • @karthick, This looks promising. But will it cause IIS *delete* my files, or do I need to devise a mechanism for that myself? – Stephen Collins Jul 15 '14 at 12:52

1 Answers1

2

Try this:

When you add your file, insert it into the HttpRuntimeCache and set the Key to the FileName and set the TimeOut to say 10 seconds. Then on the CacheItemRemoved callback, delete the file. It's not exact, but it should roughly meet your use case.

public static object LoadFile()
{
    var filename = ParseFileNameFromHttpRequest();

    var a = loadFileSomeHow(filename);

    HttpRuntime.Cache.Insert(
        filename ,
        a, 
        null,
        System.Web.Caching.Cache.NoAbsoluteExpiration,
        new TimeSpan(0, 0, 0,10,0,0),
        CacheItemPriority.Default,
        new CacheItemRemovedCallback(DeleteFile));

    return a;
}

public void DeleteFile(String key, object value,
    CacheItemRemovedReason removedReason)
{
    File.Delete(key);
}

For more info: http://msdn.microsoft.com/en-us/library/vstudio/7kxdx246(v=vs.100).aspx

Philip Pittle
  • 11,821
  • 8
  • 59
  • 123
  • 1
    This works great! Thank you! As a side note, (at least in my case) it's unnecessary to put the file itself into the cache; I just put the filename into the key *and* value fields and the callback handles the rest. – Stephen Collins Jul 15 '14 at 14:15
  • 1
    Excellent to hear! Depending on your platform, you might want to test this and make sure it still works under heavy load, if that is a valid use case. – Philip Pittle Jul 15 '14 at 14:19