Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Stream file from S3 to browser, assume Laravel Filesystem usage
<?php
/*************************************************************************
* Get File Information
*/
// Assuming these come from some data source in your app
$s3FileKey = 's3/key/path/to/file.ext';
$fileName = 'file.ext';
// Create temporary download link and redirect
$adapter = Storage::disk('s3')->getAdapter();
$client = $adapter->getClient();
$client->registerStreamWrapper();
$object = $client->headObject([
'Bucket' => $adapter->getBucket(),
'Key' => /*$adapter->getPathPrefix() . */$s3FileKey,
]);
/*************************************************************************
* Set headers to allow browser to force a download
*/
header('Last-Modified: '.$object['LastModified']);
// header('Etag: '.$object['ETag']); # We are not implementing validation caching here, but we could!
header('Accept-Ranges: '.$object['AcceptRanges']);
header('Content-Length: '.$object['ContentLength']);
header('Content-Type: '.$object['ContentType']);
header('Content-Disposition: attachment; filename='.$fileName);
/*************************************************************************
* Stream file to the browser
*/
// Open a stream in read-only mode
if (!($stream = fopen("s3://{$adapter->getBucket()}/{$s3FileKey}", 'r'))) {
throw new \Exception('Could not open stream for reading file: ['.$s3FileKey.']');
}
// Check if the stream has more data to read
while (!feof($stream)) {
// Read 1024 bytes from the stream
echo fread($stream, 1024);
}
// Be sure to close the stream resource when you're done with it
fclose($stream);
@fideloper

This comment has been minimized.

Copy link
Owner Author

commented Aug 7, 2017

Reference:

Docs on HeadObject S3 API call:

http://docs.aws.amazon.com/aws-sdk-php/v3/api/api-s3-2006-03-01.html#headobject

Example streaming file and explanation on "$client->registerStreamWrapper()" method:

https://aws.amazon.com/blogs/developer/amazon-s3-php-stream-wrapper/

Force file download via Content-Disposition header:

https://stackoverflow.com/questions/8485886/force-file-download-with-php-using-header

@kingsloi

This comment has been minimized.

Copy link

commented Mar 23, 2018

Hey @fideloper, I bought your Scaling Laravel course and slowly but surely implementing all that good stuff into my app! I've just implemented your S3FileStream class, but not 100% sure how to test (or specially how to mock S3). Can you share any ideas your have re: testing against that class?

@skmetaly

This comment has been minimized.

Copy link

commented Apr 18, 2018

hey @fideloper . There's an extra paranthesis at the end of

header('Content-Disposition: attachment; filename='.$fileName));

causing a syntax error

Fideloper Update: Fixed that, thanks!

@robfrancken

This comment has been minimized.

Copy link

commented May 29, 2018

@fideloper thanks so much, saved me hours.

@nwaughachukwuma

This comment has been minimized.

Copy link

commented Nov 18, 2018

@fideloper thanks for this

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.