0

I save documents uploaded from a website in Amazon's S3. I store the file with a unique hash, to eliminate the possibility of duplicates.

I can download the files to the server with the correct filename.

How do I download the files to the users browser instead of the server? I use Donovan Schonknecht's S3 library and I use the S3::getObject to read the file.

Other possibility, is it possible to link a URL like https://s3.amazonaws.com/myfolder/d_b5592038c76db88c4c6113d1fb166fe8e9b1b7b3.pdf and download it to a browser as myfile.pdf?

I don't want to download the file to the server and then to the user.

andrebruton
  • 2,268
  • 4
  • 29
  • 36
  • This is similar to another question I have answered before that uses the AWS SDK for PHP: http://stackoverflow.com/questions/18839216/download-file-from-amazon-s3-with-laravel/18852936#18852936 – Jeremy Lindblom Feb 18 '15 at 19:24

2 Answers2

0

Thanks for the comments and email leads... The solution is to use headers and readfile. I used David Walsh's header example http://davidwalsh.name/php-force-download and combined it with php's readfile. The readfile reads the file with the hash name and the headers saves it with another name. The original filename or location is never shown to the public. Here is some useful php code:

// get doc details
$stmt = $conn->prepare("SELECT * FROM docs WHERE docs_hash = :hash LIMIT 1 ");
$stmt->execute(array(':hash' => $docs_hash));
$result = $stmt;

if ($result->rowCount() > 0) {

  foreach($result as $row) {

    $docs_filename    = $row['docs_filename'];
    $docs_extension   = $row['docs_extension'];
    $docs_downloaded  = $row['docs_downloaded'];
    $download_file = "doc_" . $docs_hash . "." . $docs_extension;
  }

  // echo "File 1: $download_file <br>";
  // echo "File 2: $docs_filename <br>";
  // echo "Bucket: " . _AWS_BUCKET_ . "<br>";

  // required for IE
  if (ini_get('zlib.output_compression')) { ini_set('zlib.output_compression', 'Off');  }

  // get the file mime type using the file extension
  switch(strtolower(substr(strrchr($docs_filename, '.'), 1))) {
    case 'pdf': $mime = 'application/pdf'; break;
    case 'zip': $mime = 'application/zip'; break;
    case 'jpeg':
    case 'jpg': $mime = 'image/jpg'; break;
    default: $mime = 'application/force-download';
  }
  header('Pragma: public');     // required
  header('Expires: 0');     // no cache
  header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
  header('Cache-Control: private', false);
  header('Content-Type: ' . $mime);
  header('Content-Disposition: attachment; filename="' . basename($docs_filename) . '"');
  header('Content-Transfer-Encoding: binary');
  header('Connection: close');
  readfile("https://s3.amazonaws.com/" . _AWS_BUCKET_ . "/" . $download_file);
  exit();

}
andrebruton
  • 2,268
  • 4
  • 29
  • 36
0

You can try AWS-SDK (official). The main idea is to get a signed url from S3 services so you can make a download link available for your site users, without implementing server side code. You can make it entirely with Javascript.

More information on: http://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#getSignedUrl-property