Download file from Amazon S3 with Laravel

15,170

Solution 1

The S3Client::getObject() method allows you to specify headers that S3 should use when it sends the response. The getObjectUrl() method uses the GetObject operation to generate the URL, and can accept any valid GetObject parameters in its last argument. You should be able to do a direct S3-to-user download with your desired headers using a pre-signed URL by doing something like this:

$downloadUrl = $s3->getObjectUrl($bucket, 'data.txt', '+5 minutes', array(
    'ResponseContentDisposition' => 'attachment; filename="' . $fileName . '"',
));

If you want to stream an S3 object from your server, then you should check out the Streaming Amazon S3 Objects From a Web Server article on the AWS Developer Guide

Solution 2

This question is not answered fully. Initially it was asked to how to save a file locally on the server itself from S3 to make use of it.

So, you can use the SaveAs option with getObject method. You can also specify the version id if you are using versioning on your bucket and want to make use of it.

$result = $this->client->getObject(array(
'Bucket'=> $bucket_name,
'Key'   => $file_name,
'SaveAs'  => $to_file,
'VersionId' => $version_id));

Solution 3

The answer is somewhat outdated with the new SDK. The following works with v3 SDK.

$client->registerStreamWrapper();
$result = $client->headObject([
    'Bucket' => $bucket,
    'Key'    => $key
]);

$headers = $result->toArray();

header('Content-Type: ' . $headers['ContentType']);
header('Content-Disposition: attachment');

// Stop output buffering
if (ob_get_level()) {
    ob_end_flush();
}

flush();

// stream the output
readfile("s3://{$bucket}/{$key}");
Share:
15,170
Prash
Author by

Prash

Freelance web developer based in the UK

Updated on June 09, 2022

Comments

  • Prash
    Prash almost 2 years

    I'm a little sure as to how to launch a download of a file from Amazon S3 with Laravel 4. I'm using the AWS

    $result = $s3->getObject(array(
        'Bucket' => $bucket,
        'Key'    => 'data.txt',
    ));
    
    // temp file
    $file = tempnam('../uploads', 'download_');
    
    file_put_contents($file, $result['Body']);
    
    $response = Response::download($file, 'test-file.txt');
    
    //unlink($file);
    
    return $response;
    

    The above works, but I'm stuck with saving the file locally. How can I use the result from S3 correctly with Response::download()?

    Thanks!

    EDIT: I've found I can use $s3->getObjectUrl($bucket, $file, $expiration) to generate an access URL. This could work, but it still doesn't solve the problem above completely.

    EDIT2:

    $result = $s3->getObject(array(
        'Bucket' => $bucket,
        'Key'    => 'data.txt',
    ));
    
    header('Content-type: ' . $result['ContentType']);
    header('Content-Disposition: attachment; filename="' . $fileName . '"');
    header('Content-length:' . $result['ContentLength']);
    
    echo $result['Body'];
    

    Still don't think it's ideal, though?