2

I have an ASP.NET WebAPI project where I need to generate XLS or PDF's depending on the client (jQuery) request.

Because it's not possible to download a file using $.ajax, the approach is pretty simple:

  1. I will request via $.ajax the generation of the file (XLS or PDF) on server.

    but instead of sending the response from server to the client I will save the file locally. The filename will be: some_token.xls. The token should be unique. Maybe a GUID.

  2. After the file is generated and saved on server, the method will response with a 200 status and the token just generated (that actually is the filename).
  3. My jQuery ajax request method will enter into success function and then will append the "src" property of an IFrame with the path and token of the just generated file.
  4. The server will download the file and will delete it.
So my jQuery ajax looks like this:
 $.ajax({
    // the url used to generate the file and save it on server
    url: '/api/requestfile',
    contentType: "application/json; charset=utf-8",
    data: myData,
    dataType: "json",
    cache: false,
    type: 'POST',
    success: function (data) {
        if (data) {
            // if the file was created successfuly on server then download the file
            var iframe = $("<iframe/>").attr({
                src: 'api/downloadfile/' + data.filetoken, // filetoken generated in server
                style: "visibility:hidden;display:none"
            }).appendTo(buttonToDownloadFile);
        } else {
            alert('Something went wrong');
        }
    }
})

So I have several questions:

a) Where is the right server path to save the file that I will generate? (AppData, customFolder..?


b) Is there any best practice to create tokens as file names or just using a GUID is fine?


c) How can I delete the file in server once it's downloaded? The file won't be accessed by any other user because the file is created by request. So it's a one time file.

UPDATED SOLUTION:

a) The solution was to create a "TempFiles" directory inside App_Data folder that is used to store data.

b) I create a random function to generate a token:

public static string GetRandomToken(int length) {
    int intZero = '0';
    int intNine = '9';
    int intA = 'A';
    int intZ = 'Z';
    int intCount = 0;
    int intRandomNumber = 0;
    string strDownloadToken = "";
    Random objRandom = new Random(System.DateTime.Now.Millisecond);
    while (intCount < length) {
        intRandomNumber = objRandom.Next(intZero, intZ);
        if (((intRandomNumber >= intZero) &&
            (intRandomNumber <= intNine) ||
            (intRandomNumber >= intA) && (intRandomNumber <= intZ))) {
            strDownloadToken = strDownloadToken + (char) intRandomNumber;
            intCount++;
        }
    }
    return strDownloadToken;
}

c) Because I'm using WebAPI the delete is a little bit different. I had to create a Filter:

public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext) {
    // here I added the code to delete the file.
    // this Filter is executed after the file response have been sent to server so its safe now to delete the file
}
VAAA
  • 14,531
  • 28
  • 130
  • 253

1 Answers1

0

In the comments @MikeCheel is probably right about how to build this, but if you are intent on building a server side solution

A) Where is the right server path to save the file that I will generate? (AppData, customFolder..)

Custom folder that is NOT accessible to the outside world. Then create a handler that serves up the file based on say a url parameter. IE. mywebsite.com/getFile?id=23434234 or some such. In the handler you can easily add security and other checks. Also it will come in handy for C.

You could of course go with a custom folder that is accessible, but that's usually frowned upon

b) Is there any best practice to create tokens as file names or just using a GUID is fine?

No real best practice, you'd like them to not be easily guessable. A Guid would work fine.

c) How can I delete the file in server once it's downloaded? The file won't be accessed by any other user because the file is created by request. So it's a one time file.

If you use the handler above, you can serve up the file and then delete it. Otherwise you might need a process that periodically deletes the temp files. Without a handler, I'm not sure how to keep track that the file was actually downloaded the one time or if it was never downloaded, or downloaded 100 times.

Prescott
  • 7,312
  • 5
  • 49
  • 70