I am successfully uploading folders to S3 using ->uploadDirectory(). Several hundred folders have 100's, or 1,000's of images contained within them with so using PutObject() for each file hardly seemed to make sense. The upload works, and all goes well, but the ACL, StorageClass, and metadata is not being included in the upload.
According to the docs at http://docs.aws.amazon.com/aws-sdk-php/v2/guide/service-s3.html#uploading-a-directory-to-a-bucket , the following code should accomplished this. It is further documented with the putObject() function that is also cited.
I can find no examples of this function using anything but a directory and bucket, so fail to see what might be wrong with it. Any ideas why the data in $options is being ignored?
$aws = Aws::factory('config.php');
$s3 = $aws->get('S3');
$dir = 'c:\myfolder\myfiles';
$bucket = 'mybucket;
$keyPrefix = "ABC/myfiles/";
$options = array(
'ACL' => 'public-read',
'StorageClass' => 'REDUCED_REDUNDANCY',
'Metadata'=> array(
'MyVal1'=>'Something',
'MyVal2'=>'Something else'
)
);
$result = $s3->uploadDirectory($dir, $bucket, $keyPrefix, $options);
Parameters to provide to putObject or createMultipartUpload should be in the params option, not provided as top-level values in the options array. Try declaring your options as follows:
$options = array(
'params' => array(
'ACL' => 'public-read',
'StorageClass' => 'REDUCED_REDUNDANCY',
'Metadata'=> array(
'MyVal1'=>'Something',
'MyVal2'=>'Something else',
),
),
);
Related
I am using AWS SDK, and I am able to create buckets and manipulate keys. At the time of creation of bucket I also want to enable it for website hosting.
This is what I am using for creation
$result = $s3->createBucket([
'Bucket' => $buck_name
]);
From what I found, This is how we add website configuration
$result = $s3->putBucketWebsite(array(
'Bucket' => $buck_name,
'IndexDocument' => array('Suffix' => 'index.html'),
'ErrorDocument' => array('Key' => 'error.html'),
));
But this is not enabling website hosting,I also have uploaded both files(index and error) just in case. But I am getting this error
InvalidArgumentException: Found 1 error while validating the input provided for the PutBucketWebsite operation: [WebsiteConfiguration] is missing and is a required parameter in
Try this way
use Aws\S3\S3Client;
$bucket = $buck_name;
// 1. Instantiate the client.
$s3 = S3Client::factory();
// 2. Add website configuration.
$result = $s3->putBucketWebsite(array(
'Bucket' => $bucket,
'IndexDocument' => array('Suffix' => 'index.html'),
'ErrorDocument' => array('Key' => 'error.html'),
));
// 3. Retrieve website configuration.
$result = $s3->getBucketWebsite(array(
'Bucket' => $bucket,
));
echo $result->getPath('IndexDocument/Suffix');
Here is my code, which works for forms upload (via $_FILES) (I'm omitting that part of the code because it is irrelevant):
$file = "http://i.imgur.com/QLQjDpT.jpg";
$s3 = S3Client::factory(array(
'region' => $region,
'version' => $version
));
try {
$content_type = "image/" . $ext;
$to_send = array();
$to_send["SourceFile"] = $file;
$to_send["Bucket"] = $bucket;
$to_send["Key"] = $file_path;
$to_send["ACL"] = 'public-read';
$to_send["ContentType"] = $content_type;
// Upload a file.
$result = $s3->putObject($to_send);
As I said, this works if file is a $_FILES["files"]["tmp_name"] but fails if $file is a valid image url with Uncaught exception 'Aws\Exception\CouldNotCreateChecksumException' with message 'A sha256 checksum could not be calculated for the provided upload body, because it was not seekable. To prevent this error you can either 1) include the ContentMD5 or ContentSHA256 parameters with your request, 2) use a seekable stream for the body, or 3) wrap the non-seekable stream in a GuzzleHttp\Psr7\CachingStream object. You should be careful though and remember that the CachingStream utilizes PHP temp streams. This means that the stream will be temporarily stored on the local disk.'. Does anyone know why this happens? What might be off? Tyvm for your help!
For anyone looking for option #3 (CachingStream), you can pass the PutObject command a Body stream instead of a source file.
use GuzzleHttp\Psr7\Stream;
use GuzzleHttp\Psr7\CachingStream;
...
$s3->putObject([
'Bucket' => $bucket,
'Key' => $file_path,
'Body' => new CachingStream(
new Stream(fopen($file, 'r'))
),
'ACL' => 'public-read',
'ContentType' => $content_type,
]);
Alternatively, you can just request the file using guzzle.
$client = new GuzzleHttp\Client();
$response = $client->get($file);
$s3->putObject([
'Bucket' => $bucket,
'Key' => $file_path,
'Body' => $response->getBody(),
'ACL' => 'public-read',
'ContentType' => $content_type,
]);
You have to download the file to the server where PHP is running first. S3 uploads are only for local files - which is why $_FILES["files"]["tmp_name"] works - its a file that's local to the PHP server.
I'm trying to upload an image to an AWS s3 bucket that I have created, so I have copied an pasted the standard code from the AWS documentation to accomplish this but I get an absolute blank page. Like even if I put an echo 'hi' before any statements, even that doesn't show up. Wondering if anyone can please help shed light on this topic.
<?php
//this is the path to my S3 resource
use PHP\resources\aws\Aws\S3\S3Client;
$bucket = 'i put my bucket name here';
$keyname = 'yoyo';
// $filepath should be absolute path to a file on disk
$filepath = 'images/verified.png';
// Instantiate the client.
$s3 = S3Client::factory(array(
'profile' => 'default',
));
//the contents of my credentials.ini file are
//[default]
//aws_access_key_id = myaccessidhere
//aws_secret_access_key = mysecretkeyhere
// Upload a file.
$result = $s3->putObject(array(
'Bucket' => $bucket,
'Key' => $keyname,
'SourceFile' => $filepath,
'ACL' => 'public-read',
'StorageClass' => 'REDUCED_REDUNDANCY',
)
));
echo $result['ObjectURL'];
echo 'done';
?>
Does anyone know why this code doesn't work at all? I would really really appreciate any help offerd, thank - you!
I'm trying to upload a file to my bucket. I am able to upload with Body but not SourceFile. Here's my method:
$pathToFile='/explicit/path/to/file.jpg'
// Upload an object by streaming the contents of a file
$result = $s3Client->putObject(array(
'Bucket' => $bucket,
'Key' => 'test.jpg',
'SourceFile' => $pathToFile,
'ACL' => 'public-read',
'ContentType' => 'image/jpeg'
));
but I get this error:
You must specify a non-null value for the Body or SourceFile parameters.
I've tried different types of files and keep getting this error.
The issue had to do with not giving a good path. Looks like file_exists() only checks locally, meaning that it had to be within localhost's index.
Change
'SourceFile' => $pathToFile,
to
'Body' => $pathToFile,
I'm having problems setting the "Metadata" option when uploading files to Amazon S3 using the AWS SDK PHP v2. The documentation that I'm reading for the upload() method states that the the 5th parameter is an array of options...
*$options Custom options used when executing commands: - params: Custom
parameters to use with the upload. The parameters must map to a
PutObject or InitiateMultipartUpload operation parameters. -
min_part_size: Minimum size to allow for each uploaded part when
performing a multipart upload. - concurrency: Maximum number of
concurrent multipart uploads. - before_upload: Callback to invoke
before each multipart upload. The callback will receive a
Guzzle\Common\Event object with context.*
My upload() code looks like this..
$upload = $client->upload(
'<BUCKETNAME>',
'metadatatest.upload.jpg',
fopen('metadatatest.jpg','r'),
'public-read',
array('Metadata' => array(
'SomeKeyString' => 'SomeValueString'
))
);
...and no meta data is set after upload.
If however I use putObject() as documented here, which I assume is a "lower level" method compared to upload()...
$putObject = $client->putObject(
array(
'Bucket' => '<BUCKETNAME>',
'Key' => 'metadatatest.putobject.jpg',
'Body' => file_get_contents('metadatatest.jpg'),
'ACL' => 'public-read',
'Metadata' => array(
'SomeKeyString' => 'SomeValueString'
)
)
);
The meta data is successfully returned when I call getObject() or view the file directly in my browser when uploaded using putObject()
$getObject = $client->getObject(
array(
'Bucket' => '<BUCKETNAME>',
'Key' => 'metadatatest.putobject.jpg'
)
);
I would prefer to use the $client->upload() method as the documentation states
Upload a file, stream, or string to a bucket. If the upload size exceeds the specified threshold, the upload will be performed using
parallel multipart uploads.
I'm not sure what I've missed?
There's really no difference in using upload() or putObject() if you don't do multipart uploads. You can have a look at the AWS PHP SDK source code but basically the upload method just calls putObject like this:
// Perform a simple PutObject operation
return $this->putObject(array(
'Bucket' => $bucket,
'Key' => $key,
'Body' => $body,
'ACL' => $acl
) + $options['params']);
This isn't very clear in the SDK documentation, but you need to send the last parameter as an array with the key params and its value being a second array with the Metadata key and value like this:
$upload = $client->upload(
'<BUCKETNAME>',
'metadatatest.upload.jpg',
fopen('metadatatest.jpg','r'),
'public-read',
array('params' => array(
'Metadata' => array(
'SomeKeyString' => 'SomeValueString'
)))
);
However, I you could just use the putObject call to achieve the same thing.