Forcing Download from s3 amazon servers

24,804

Solution 1

You just need to set the correct headers on your files in S3 in order to force the browser to download rather than opening the file. Set these:

Content-Disposition: attachment; filename=FILENAME.EXT
Content-Type: application/octet-stream

You will need to set them when uploading the files to S3. With the php SDK you'd use create_object.

Or you can set these after uploading using 'change_content_type' or by copying the file to itself in S3 and setting the correct headers.

Solution 2

Bit late to the party, but often times with a file you don't want to have to decide at storage time how it will be used. You want to be able to store the file once, then in one area possibly embed the file or display in browser, and in another area enable the user to download the same file.

Fortunately you can do that by providing override parameters in the request url. It only works with signed requests, but thankfully you're already doing that.

If you add a parameter like &request-content-type="application/force-download" that should do the trick.

Check out the Request Parameters section of the S3 GET Object documentation: http://docs.aws.amazon.com/AmazonS3/latest/API/RESTObjectGET.html

Solution 3

The question is about setting this programmatically, but to do so manually through the AWS console:

  • Select a file in S3.
  • Properties > Metadata > Add more metadata
  • Key: Content-Disposition Value: Attachment
  • Save
Share:
24,804

Related videos on Youtube

Khaled
Author by

Khaled

Updated on July 09, 2022

Comments

  • Khaled
    Khaled almost 2 years

    I've been developing a new web application which relies on Amazon S3 servers as storage system, and Codeiginter as the PHP framework.

    I need to force the file to download when the link is clicked. The original URL looks like this:

    http://www.our-web.com/download/do/1.jpg

    which generates a temporary signed URL to the actual file on the Amazon S3 servers like this:

    http://main_bucket.s3.amazonaws.com/post/1/1.jpg?AWSAccessKeyId=AKIAJEOQKYPKC3CCU5RA&Expires=1305395426&Signature=iuzCdA22gImLK192%2BMAhk8OkAY8%3D

    I need to make the file start downloading from the real Amazon URL it soon as the user clicks the link.

    I have two ways now to do so:

    1. Use redirect() which will open the file not download it; or
    2. Alter headers as this code:

      header('Content-type: application/force-download');
      header('Content-Disposition: attachment; filename=' . $file_name);
      header('Content-Transfer-Encoding: binary');
      header('Expires: 4000');
      header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
      header('Pragma: public');
      header('Content-Length: ' . filesize($generated_file));
      
      readfile($generated_file);
      

    Unfortunately, both ways don't help me. The second method causes the download to come from my website and not from directly from Amazon.

    How can I force the file to download directly from the Amazon S3 servers, and not from my website?

    • Lawrence Cherone
      Lawrence Cherone about 13 years
      use file_get_contents or a cURL to retrive the S3 file then do a passthrough with the headers
    • Lasar
      Lasar about 13 years
      That's what he'd doing with readfile.
    • Khaled
      Khaled about 13 years
      correct, but even though I don't want the client to download the file through my website. there must be a better solution to download from another domain.
    • Loving Android
      Loving Android almost 13 years
      Pulling the file through your site is a terrible idea if you're trying to take advantage of cloudfront, which potentially distributes your content to up to 19 edge nodes.
  • Khaled
    Khaled about 13 years
    the image is just an example, maybe I forget to mention that several files type is allowed specially pdf, and docx. Anyway, thanks for the responce, but I think there is a way to figure this out. Actually many big websites uses external storage system.
  • Khaled
    Khaled about 13 years
    it's been solved by changing the file meta as this code says: $opt['meta']['Content-Type'] = 'binary/octet-stream';
  • Geoff Appleford
    Geoff Appleford about 13 years
    @Khaled - Great. Glad to help:)
  • Lasar
    Lasar about 13 years
    I was not aware of the possibility of setting headers when uploading a file to S3. That is nice to know.
  • Khaled
    Khaled about 13 years
    it is possible, I think amazon has yet has better solutions to provide, the reason why we chosen amazon s3 because it has direct upload using POST directly from browser. thanks for the help anyway
  • Nick
    Nick over 8 years
    Very useful since this answer ranks highly in google searches, and I needed to show a non tech person how to do this on AWS.
  • Seth
    Seth over 7 years
    I believe the correct request parameter is request-content-disposition=attachment; filename=FILENAME.EXT". Your request-content-type is working because it's an unknown content type so the browser downloads it by default.
  • Simon East
    Simon East about 7 years
    Brilliant, yes this is what I was after. Would rather not decide this at storage time (particularly since there's thousands of files already in S3 that I don't want to have to modify).
  • dmitrybelyakov
    dmitrybelyakov almost 6 years
    I believe the only thing actually needed is content disposition header. No need to set content type.
  • Luke
    Luke over 4 years
    as of 2019 it's actually response-content-disposition=attachment;%20FILENAME.EXT
  • Gerbus
    Gerbus almost 4 years
    Documentation for Luke's comment here docs.aws.amazon.com/AmazonS3/latest/API/…