
Editorial illustration.
Originally published 16 June 2023; rewritten and reviewed on 15 October 2026.
A download endpoint accepts a bucket key and returns the matching file. It works in a demonstration, but a caller can now ask for keys the interface never displayed. I would resolve the object through an authorised application record before making the storage request.
Authorise the document, then find its object
Use a document identifier owned by the application. Check the requesting user’s access, then read the associated bucket and key from trusted storage. Do not treat an opaque-looking path as evidence of permission.
A core C# AWS SDK retrieval looks like this, using a configured client:
using var response = await s3.GetObjectAsync(
new GetObjectRequest
{
BucketName = bucketName,
Key = authorisedObjectKey
}, cancellationToken);
await response.ResponseStream.CopyToAsync(
destinationStream, cancellationToken);
Keep response and destination lifetimes aligned with the surrounding application. In a web action, a stream cannot be disposed before the framework finishes sending it.
Choose a delivery strategy
Proxying the object through the application gives one kind of control and resource cost. A short-lived presigned URL is another option when its bearer-style access fits the requirement. Set the expiry and response behaviour deliberately, and avoid recording signed URLs unnecessarily in logs.
Use a safe download filename and the intended content-disposition behaviour. A trusted object key does not make every stored content type safe to render inline.
Handle failures meaningfully
Distinguish cancellation, an unavailable object and an internal configuration error in logs, while returning a response that does not reveal another user’s documents. Test a removed object and a denied storage permission separately.
A dependable download preserves the application’s access decision all the way to the bytes the user receives.