1

I have to log the download requests for each file that is grabbed off of a website. This log has to have the Employee ID, Solution ID, IP Address. I've used quite a few methods -

First, I was using a model where I was putting the path of the file in an anchor tag . Whenever the user clicked on this anchor tag, I was generating an AJAX request to log the file download.

But the huge drawback of this is that the user can just copy the file and paste it in a seperate window to get the file. That would ensure that the download was not logged.

Second, When I was processing the ajax request in the web method in a page. I tried transmitting the file through HttpResponse, but that didn't work either.

HttpContext.Current.Response.TransmitFile("filename");

jQuery ajax call kept failing, and I never got the file on the client side.

The key thing is, I have to do the whole thing without refreshing the page.

I'm wondering if this is possible at all...

Abijeet Patro
  • 2,842
  • 4
  • 37
  • 64

3 Answers3

3

You could implement a IHttpHandler that logs the request, retrieves the file and serves it. This way, even if the link is copied and pasted directly, it would still log it.

public class SimpleHandler : IHttpHandler
{
    public bool IsReusable
    {
        get { return false; }
    }

    public void ProcessRequest(HttpContext context)
    {
        string fileToServe = context.Request.QueryString["file"];

        if (!string.IsNullOrEmpty(fileToServe))
        {
            //Log request here...

            context.Response.ContentType = "content type for your file here";
            context.Response.WriteFile("~/path/" + fileToServe);
        }
    }
}
Community
  • 1
  • 1
Dennisch
  • 6,888
  • 1
  • 17
  • 32
1

This is very much possible – you need to return a file as a response to an action (Mvc) or to an aspx page (webforms). So when the action or aspx page is hit you can log the request and write the file to the response.

Edit: for webforms example, see this SO question

For mvc:

public ActionResult DownloadFile(string fileHint)
{
    // log what you want here.
    string filePath = "determine the path of the file to download maybe using fileHint";
    return File(filePath, "application/octet-stream"); // second argument represents file type; in this case, it's a binary file.
}
Community
  • 1
  • 1
Varun K
  • 3,593
  • 2
  • 25
  • 26
  • Sorry ASP.NET web forms only – Abijeet Patro Aug 14 '13 at 11:49
  • @AbijeetPatro As refered in my answer, You can look at [this SO question](http://stackoverflow.com/questions/4088962/net-mvc-fileresult-equivalent-in-web-forms) to return file from an aspx page. on page_load, you can log user request and then write the file to Response as mentioned in that link. – Varun K Aug 14 '13 at 11:58
  • I can't reload the page. :( – Abijeet Patro Aug 14 '13 at 12:01
1

You could use the AJAX method, with an identifier in the link to be used as a parameter value to refer to the file - rather than storing the full path - and have your web method return the serialized data of the file.

So, your web method might look something like this:

[WebMethod]
public static string GetDownload(string someIdentifier) {
  // get the contents of your file, then...
  // do your logging, and...
  var serializer = new JavaScriptSerializer();
  return serializer.Serialize(fileByteArrayOrSuch);
}

Then handle the file contents on the client side. There will doubtless be some more trifling elements to add to your function for the sake of logging; but the bottom line is, your AJAX can both handle logging and then process the download request.

Grant Thomas
  • 44,454
  • 10
  • 85
  • 129