Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Create temporary link for download

I use ASP.NET
I need to give user temporary link for downloading file from server.
It should be a temporary link (page), which is available for a short time (12 hours for example). How can I generate this link (or temporary web page with link)?

like image 570
Ilya Blokh Avatar asked Apr 18 '11 12:04

Ilya Blokh


3 Answers

Here's a reasonably complete example.

First a function to create a short hex string using a secret salt plus an expiry time:

public static string MakeExpiryHash(DateTime expiry)
{
    const string salt = "some random bytes";
    byte[] bytes = Encoding.UTF8.GetBytes(salt + expiry.ToString("s"));
    using (var sha = System.Security.Cryptography.SHA1.Create())
        return string.Concat(sha.ComputeHash(bytes).Select(b => b.ToString("x2"))).Substring(8);
}

Then a snippet that generates a link with a one week expiry:

DateTime expires = DateTime.Now + TimeSpan.FromDays(7);
string hash = MakeExpiryHash(expires);
string link = string.Format("http://myhost/Download?exp={0}&k={1}", expires.ToString("s"), hash);

Finally the download page for sending a file if a valid link was given:

DateTime expires = DateTime.Parse(Request.Params["exp"]);
string hash = MakeExpiryHash(expires);
if (Request.Params["k"] == hash)
{
    if (expires < DateTime.UtcNow)
    {
        // Link has expired
    }
    else
    {
        string filename = "<Path to file>";
        FileInfo fi = new FileInfo(Server.MapPath(filename));
        Response.ContentType = "application/octet-stream";
        Response.AddHeader("Content-Disposition", "attachment;filename=" + filename);
        Response.AddHeader("Content-Length", fi.Length.ToString());
        Response.WriteFile(fi.FullName);
        Response.Flush();
    }
}
else
{
    // Invalid link
}

Which you should certainly wrap in some exception handling to catch mangled requests.

like image 78
Hugh W Avatar answered Oct 11 '22 10:10

Hugh W


http://example.com/download/document.pdf?token=<token>

The <token> part is key here. If you don't want to involve a database, encrypt link creation time, convert it to URL-safe Base64 representation and give user that URL. When it's requested, decrypt token and compare date stored in there with current date and time.

Alternatively, you can have a separate DownloadTokens table wich will map said tokens (which can be GUIDs) to expiration dates.

like image 9
Anton Gogolev Avatar answered Oct 11 '22 09:10

Anton Gogolev


Append a timestamp to the URL, in the querystring:

page.aspx?time=2011-06-22T22:12

Check the timestamp against the current time.

To avoid the user changing the timestamp by himself, also compute some secret hash over the timestamp, and also append that to the querystring:

page.aspx?time=2011-06-22T22:12&timehash=4503285032

As hash you can do something like the sum of all fields in the DateTime modulo some prime number, or the SHA1 sum of the string representation of the time. Now the user will not be able to change the timestamp without knowing the correct hash. In your page.aspx, you check the given hash against the hash of the timestamp.

like image 3
Sjoerd Avatar answered Oct 11 '22 09:10

Sjoerd