3

I am working on AWS ec2 ubuntu machine. My code is in cakephp. When I try to upload any image to AWS S3 it will get corrupted.

while it is working fine in core php code.

here is my controller code

 if ($this->User->saveAll($this->request->data)) {

                    // upload on s3
                    //create file name
                    // echo "<pre>"; print_r($_FILES); die;
                    $temp = explode(".", $_FILES["data"]["name"]["User"]['image']);
                    $newfilename = round(microtime(true)) . '.' . end($temp);

                    $filepath = $_FILES['data']['tmp_name']['User']['image'];
                    $id = $this->request->data['User']['id'];

                    try {
                        $result = $this->Amazon->S3->putObject(array(
                            'Signature' => 'v4',
                            'Bucket' => 'abc.sample',
                        'ACL' => 'authenticated-read',
                        'Key' => 'files/user/image/' . $id . "/" . $newfilename,
                        'ServerSideEncryption' => 'aws:kms',
                        'SourceFile' => $filepath,
                        'Body' => $filepath,
                        'ContentType' => $_FILES['data']['type']['User']['image'],

                    ));
                } catch (S3Exception $e) {
                    echo $e->getMessage() . "\n";
                }
}

One more thing if I didn't use body parameter then it is showing me following error

You must specify a non-null value for the Body or SourceFile parameters.

While following code is working fine for test in core php

$filepath = "/var/www/html/for_testing_aws/assets/img/avtar.png";

try {
    $result = $s3->putObject(array(
        'Bucket' => $bucketName,
        'ACL' => 'authenticated-read',
        'Key' => "avtar-auth.png",
        'ServerSideEncryption' => 'aws:kms',
        'SourceFile' => $filepath,
        'ContentType' => mime_content_type($filepath),
        'debug' => [
            'logfn' => function ($msg) {
                echo $msg . "\n";
            },
            'stream_size' => 0,
            'scrub_auth' => true,
            'http' => true,
        ],
    ));
} catch (S3Exception $e) {
    echo $e->getMessage() . "\n";
}

I create a custom component for accessing all features of SDK. with the reference of https://github.com/Ali1/cakephp-amazon-aws-sdk.

check this

enter image description here

Images saving properly on my ec2 storage. for image uploading on ec2 server I am using this plugin https://github.com/josegonzalez/cakephp-upload

I try putobject with simple form uploading approach which also work for me here is the code

require 'aws-autoloader.php';

$credentials = new Aws\Credentials\Credentials('key 1', 'key2');
$bucketName = "";
$s3 = new Aws\S3\S3Client([
   // 'signature' => 'v4',
    'version' => 'latest',
    'region' => 'ap-southeast-1',
    'credentials' => $credentials,
    'http' => [
        'verify' => '/home/ubuntu/cacert.pem'
    ],
    'Statement' =>[
        'Action '=> "*",
    ],
//    'debug' => [
//        'logfn' => function ($msg) {
//            echo $msg . "\n";
//        },
//        'stream_size' => 0,
//        'scrub_auth' => true,
//        'http' => true,
//    ]
        ]);

$result = $s3->listBuckets();
foreach ($result['Buckets'] as $bucket) {
    // Each Bucket value will contain a Name and CreationDate

     $bucketName = $bucket['Name'];
}

 <form name="uploadimage" id="uploadimage" method="post" action="saveimg.php" enctype="multipart/form-data">
    <input type="file" name="file" value="file"/>
    <input type="submit" name="submit" value="submit" />
</form>

and saveimg.php is

$filepath = $_FILES['file']['tmp_name'];
try {
    $result = $s3->putObject(array(
        'Bucket' => $bucketName,
        'ACL' => 'authenticated-read',
        'Key' => $_FILES['file']['name'],
        'ServerSideEncryption' => 'aws:kms',
        'SourceFile' => $filepath,
        'ContentType' => mime_content_type($filepath),
        'debug' => [
            'logfn' => function ($msg) {
                echo $msg . "\n";
            },
            'stream_size' => 0,
            'scrub_auth' => true,
            'http' => true,
        ],
    ));
} catch (S3Exception $e) {
    echo $e->getMessage() . "\n";
}

When I try to open that file following message has shown.

enter image description here

urfusion
  • 5,528
  • 5
  • 50
  • 87
  • $filepath is not null. and there is no exception. – urfusion Aug 20 '15 at 17:05
  • It is temp location of file. – urfusion Aug 20 '15 at 17:25
  • it will get corrupted mean that i am uploading file at two place one on my ec2 server and other one is on s3. Ec2 server file is uploading correctly while facing corruption on s3. – urfusion Aug 20 '15 at 17:28
  • "corruption" is ambiguous. Do you just mean requesting the image it is broken? File sizes differ? md5s differ? body differs? mimetypes differ? If it really is completely different to the uploaded file you might need to debug the source of the lib you are using. Anyway: good luck. – AD7six Aug 20 '15 at 17:29
  • check the updated question. – urfusion Aug 20 '15 at 17:41
  • 1
    You're not an end user =). _Look_ at the source of the file - e.g. is it xml saying access denied? is it 0 bytes? You need to identify a _specific_ problem, and probably then debug from there (i.e. you may need to answer your own question). – AD7six Aug 20 '15 at 17:44
  • yes , xml saying access denied. but i am trying to open in bucket itself. and the uploaded size is only 14 bytes – urfusion Aug 20 '15 at 18:37
  • 1
    @urfusion, download the "corrupt" file from s3 **and look at its contents.** Use a text editor or a hex editor. – Michael - sqlbot Aug 20 '15 at 23:26
  • what I try to find in content.. – urfusion Aug 21 '15 at 06:50

1 Answers1

4

Try reading your file - you are passing the path and not the file contents:

'Body' => $filepath,

Should be

'Body' => file_get_contents($filepath),
timstermatic
  • 1,710
  • 14
  • 32
  • but its working without file_get_contents on my test file. And no success in live project with that. – urfusion Aug 20 '15 at 16:32
  • @timstermatic appears to be correct. Read the docs - you must specify SourceFile or Body. If you specify SourceFile you can just pass the path to the file. But if you use Body, you *must* pass in the contents of the file (using something like file_get_contents(). http://docs.aws.amazon.com/AmazonS3/latest/dev/UploadObjSingleOpPHP.html – Mike Ryan Aug 21 '15 at 14:39
  • You can verify this by downloading the "corrupt" file from S3 and opening it with a text editor. I believe it will actually be a text file containing the path to your source file. – Mike Ryan Aug 21 '15 at 14:40