I found the documentation for presigned URLS on AWS using boto to be insufficient, so here is how I formed the request.

I wanted to have a file private in S3, but expose it to a user for download if they were authorized to access it. I found the easiest way to do that was leave the object in S3 as private, but use the AWS API to generate a pre-signed URL with a low timeout (a minute or so). Unfortunately, I found the documentation not so straightforward and cobbled together a few Stack Overflow answers to come up with exactly what I needed. In particular, I needed to add the ‘ResponseContentType’ to get the file to download correctly, and needed to specify my AWS credentials.

I’m using Django to serve up the download via a get request:

class GetDownloadURL(APIView):

    def get(self, request):
        # Get the service client.
        session = boto3.session.Session(profile_name="AWSUserName")
        s3 = session.client("s3")

        # Generate the URL to get 'key-name' from 'bucket-name'
        url = s3.generate_presigned_url(
            ClientMethod="get_object",
            Params={
                "Bucket": "your-s3-bucket",
                "Key": "SampleDLZip.zip",
                "ResponseContentType": "application/zip",
            },
            ExpiresIn=100,
        )

        return Response(url)

Notes: You will need to update the Key and Bucket params to match what you have in S3. Depending how you have set up your AWS credentials, you may be able to omit the ‘profile_name=”AWSUserName”’ parameter. I prefer to be explicit in my config because I’ve run into issues when I have used the default in the past.