简体   繁体   中英

Grabbing contents of Object from S3 via PHP SDK 2?

I have been trying to figure out how to grab contents from an S3 bucket to include in a ZipArchive for a client who is storing files on S3, they now need to create reports that hold the files that were pushed up to S3 by their customers. I have tried the following with the PHP SDK 2 API (Installed with PEAR):

require 'AWSSDKforPHP/aws.phar';

use Aws\S3\S3Client;
use Aws\Common\Enum\Region;

$config = array(
    'key'    => 'the-aws-key',
    'secret' => 'the-aws-secret',
    'region' => Region::US_EAST_1
);

$aws_s3 = S3Client::factory($config);
$app_config['s3']['bucket'] = 'the-aws-bucket';
$app_config['s3']['prefix'] = '';
$attach_name = 'hosted-test-file.jpg';
try {
    $result = $aws_s3->getObject(
        array(
            'Bucket' => $app_config['s3']['bucket'],
            'Key' => $app_config['s3']['prefix'].$attach_name
        )
    );
    var_dump($result);
    $body = $result->get('Body');
    var_dump($body);
    $handle = fopen('php://temp', 'r');
    $content = stream_get_contents($handle);
    echo "String length: ".strlen($content);
} catch(Aws\S3\Exception\S3Exception $e) {
    echo "Request failed.<br />";
}

However, all it returns is an Guzzle\\Http\\EntityBody object, not sure how to grab the actual content so I can push it into the zip file.

Grabbing Object

object(Guzzle\Service\Resource\Model)[126]
    protected 'structure' => object(Guzzle\Service\Description\Parameter)[109]
    protected 'name' => null
    protected 'description' => null
    protected 'type' => string 'object' (length = 6)
    protected 'required' => boolean false
    protected 'enum' => null
    protected 'additionalProperties' => boolean true
    protected 'items' => null
    protected 'parent' => null
    protected 'ref' => null
    protected 'format' => null
    protected 'data' => array (size = 11)
        'Body' => object(Guzzle\Http\EntityBody)[97]
            protected 'contentEncoding' => boolean false
            protected 'rewindFunction' => null
            protected 'stream' => resource(292, stream)
            protected 'size' => int 3078337
            protected 'cache' => array (size = 9)
            ...
        'DeleteMarker' => string '' (length = 0)
        'Expiration' => string '' (length = 0)
        'WebsiteRedirectLocation' => string '' (length = 0)
        'LastModified' => string 'Fri, 30 Nov 2012 21:07:30 GMT' (length = 29)
        'ContentType' => string 'binary/octet-stream' (length = 19)
        'ContentLength' => string '3078337' (length = 7)
        'ETag' => string '"the-etag-of-the-file"' (length = 34)
        'ServerSideEncryption' => string '' (length = 0)
        'VersionId' => string '' (length = 0)
        'RequestId' => string 'request-id' (length = 16)

Returned from Body

object(Guzzle\Http\EntityBody)[96]
    protected 'contentEncoding' => boolean false
    protected 'rewindFunction' => null
    protected 'stream' => resource(292, stream)
    protected 'size' => int 3078337
    protected 'cache' => array (size = 9)
        'wrapper_type' => string 'php' (length = 3)
        'stream_type' => string 'temp' (length = 4)
        'mode' => string 'w+b' (length = 3)
        'unread_bytes' => int 0
        'seekable' => boolean true
        'uri' => string 'php://temp' (length = 10)
        'is_local' => boolean true
        'is_readable' => boolean true
        'is_writable' => boolean true

// Echo of strlen()
String length: 0

Any information would be high appreciated, thanks!

Solution

It me a while to figure it out but I was able to find a gist that pointed me in the right direction, in order to get the contents of the file you need to do the following:

require 'AWSSDKforPHP/aws.phar';

use Aws\S3\S3Client;
use Aws\Common\Enum\Region;

$config = array(
    'key'    => 'the-aws-key',
    'secret' => 'the-aws-secret',
    'region' => Region::US_EAST_1
);

$aws_s3 = S3Client::factory($config);
$app_config['s3']['bucket'] = 'the-aws-bucket';
$app_config['s3']['prefix'] = '';
$attach_name = 'hosted-test-file.jpg';
try {
    $result = $aws_s3->getObject(
        array(
            'Bucket' => $app_config['s3']['bucket'],
            'Key' => $app_config['s3']['prefix'].$attach_name
        )
    );
    $body = $result->get('Body');
    $body->rewind();
    $content = $body->read($result['ContentLength']);
} catch(Aws\S3\Exception\S3Exception $e) {
    echo "Request failed.<br />";
}

The body of the response is stored in a Guzzle\\Http\\EntityBody object. This is used to protect your application from downloading extremely large files and running out of memory.

If you need to use the contents of the the EntityBody object as a string, you can cast the object to a string:

$result = $s3Client->getObject(array(
    'Bucket' => $bucket,
    'Key'    => $key
));

// Cast as a string
$bodyAsString = (string) $result['Body'];

// or call __toString directly
$bodyAsString = $result['Body']->__toString();

You can also download directly to the target file if needed:

use Guzzle\Http\EntityBody;

$s3Client->getObject(array(
  'Bucket' => $bucket,
  'Key'    => $key,
  'command.response_body' => EntityBody::factory(fopen("/tmp/{$key}", 'w+'))
));

When calling getObject , you can pass in an array of options. In these options, you can specify if you want to download the object to your file system.

$bucket = "bucketName";
$file = "fileName";
$downloadTo = "path/to/save";

$opts = array(  // array of options
    'fileDownload' => $downloadTo . $file   // tells the SDK to download the 
                                             // file to this location
);

$result = $aws_s3->getObject($bucket, $file, $opts);

getObject Reference

I am not that familiar with the version 2.00 SDK, but it looks like you have been passed a stream context on php://temp . From looking at your updated question and from a brief glance at the documentation, it seems the stream may be available as:

$result = $aws_s3->getObject(
    array(
        'Bucket' => $app_config['s3']['bucket'],
        'Key' => $app_config['s3']['prefix'].$attach_name
    )
);
$stream = $result->get('stream');
$content = file_get_contents($stream);
<?php
   $o_iter = $client->getIterator('ListObjects', array(
    'Bucket' => $bucketname
   ));
   foreach ($o_iter as $o) {
    echo "{$o['Key']}\t{$o['Size']}\t{$o['LastModified']}\n";
   }

This worked for me:

$tempSave = 'path/to/save/filename.txt';

return $this->S3->getObject([
     'Bucket' => 'test',
     'Key'    => $keyName,
     'SaveAs' => $tempSave,
]);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM