Well, first you need some form of identifier. You offer a GUID, and it's easy to do, Guid.NewGuid().ToString("n") gives you that identifier.
You are talking about rewriting a URI, but it's really a little polish. Could you do some correspondence to turn /myFiles/a948ec43e5b743548fd9a77c462b953e into /myFiles/download.aspx?id=a948ec43e5b743548fd9a77c462b953e or even (after checking the lookup table) into myFiles/download.aspx?id=3 myFiles/download.aspx?fileName=myNewDownload.pdf . This is the same as any other rewriting URI task, so now just ignore it and assume that we have a request in /myFiles/download.aspx?id=a948ec43e5b743548fd9a77c462b953e , whether this is due to rewriting or not.
Good. You have an identifier, you need to match this with three things: the stream, the type of content, and the expiration date.
You can save all this in the file system, everything in the database or in the database, including the path to where the stream is stored as a file in the file system.
Say save it to a file system with names such as:
a948ec43e5b743548fd9a77c462b953e.application_pdf and a5d360178ec14e97abd556ed4b7709cf.text_plain; charset = utf-8
Please note that we do not use the usual Windows file extensions, so we can handle the case when the boot machine had different bindings to your server.
In the case of a948ec43e5b743548fd9a77c462b953e, which is the required element, we first look at the creation date, and if it's too long (the file has expired), we send a 410 GONE header with an error message explaining that the file has expired (we can also delete the file to this moment to clear use - or possibly truncate it so that it remains the record that existed for the file but has 0 bytes of memory).
Otherwise, we set Response.ContentType to "application / pdf" and then Response.TransmitFile to send the file.
If we saved the stream differently than as a file, we would like to send it in small fragments (4096 goes well with other buffers in other parts of the system), and in case of its very large call Response.Flush() periodically to prevent memory problems .
This is your main system. Nikits will include storing the original file name and sending it to the content header and submitting to range requests so that the user can resume the failed download, rather than starting from the beginning.
All of this is pretty orthogonal to any authentication used to ensure that only the right person has a file — you could use it in tandem with any type of login system, or you could leave it public, but limited in time.