Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

ralphmorris's avatar

Laravel 5.2 - Amazon S3 viewing uploaded file - AccessDenied

I am working with S3 and struggling to view an image after successfully uploading it. After uploading if I go into S3 I can see the file path etc but when I click on the link to view the file I get the following error:

<Error>
<Code>AccessDenied</Code>
<Message>Access Denied</Message>
<RequestId>1B6C94DCA39F6673</RequestId>
<HostId>
lrcpGOWch2LpGUWnkoIIUzAULqi1jgB8RV1lL6qyWe5k5t4BGImkndFdWJ2vTaS6mawN9POjyuw=
</HostId>
</Error>

This is the same error message as what I get in the network tab on chrome dev tools when I do

<img src="{{Storage::url('user/'.$user->id.'/profile_img/'.$user->profile_img)}}" alt="">

When I click the 'Make public' button on the object overview page the file then becomes available to view publicly.

I don't know much/anything about aws policies but followed this tutorial to create one that I needed for integration with Laravel.

https://wogan.blog/2017/01/04/use-amazon-s3-with-laravel-5/

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "s3:ListBucket",
                "s3:ListAllMyBuckets",
                "s3:GetBucketLocation"
            ],
            "Resource": [
                "arn:aws:s3:::bucket-name"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "s3:PutObject",
                "s3:GetObject",
                "s3:DeleteObject"
            ],
            "Resource": [
                "arn:aws:s3:::bucket-name/*"
            ]
        }
    ]
}

Is there another policy that I need to allow all uploaded objects to be publicly viewable?

I also under Manage group permissions made Object access read and permissions access read but neither made the uploaded files publicly viewable.

Any help appreciated

0 likes
10 replies
ralphmorris's avatar

Hi @edoc

Thanks for your reply. Here is the code.

        $file = Storage::put(
            'user/'.$user->id.'/profile_img/'.$fileName,
            file_get_contents($image->getRealPath())
        );
edoc's avatar

can you try @ralphmorris

$file = Storage::put(
            'user/'.$user->id.'/profile_img/'.$fileName,
            file_get_contents($image->getRealPath()),
        'public'
        );

and try to retrieve your file

1 like
ralphmorris's avatar

Hmm, didn't expect this result!

Error executing "PutObject" on "https://s3.eu-west-2.amazonaws.com/mmb-dev/user/2/profile_img/profile-image.jpg"; AWS HTTP error: Client error: `PUT https://s3.eu-west-2.amazonaws.com/mmb-dev/user/2/profile_img/profile-image.jpg` resulted in a `403 Forbidden` response:
<?xml version="1.0" encoding="UTF-8"?>
<Error><Code>AccessDenied</Code><Message>Access Denied</Message><RequestId>250F78 (truncated...)
AccessDenied (client): Access Denied - <?xml version="1.0" encoding="UTF-8"?>
<Error><Code>AccessDenied</Code><Message>Access Denied</Message><RequestId>250F781D4A19CF26</RequestId><HostId>F9d4wZHKvJjPT2l0QZOibznDnkmww0t3v3bg0OajpPtokycJova4MMgC4XCMRPUO37krCsQgZWw=</HostId></Error>

Maybe the IAM user I created doesn't have permission to make an object viewable?

ralphmorris's avatar

The are the permissions of the user:

Limited: List, Read, Write

EventFellows's avatar

Try the following:

  • use an explorer made for S3 (I use https://www.cloudberrylab.com/ which works, but there others, too)
  • Create an extra IAM user (that is the Amazon Access managment) for the explorer
  • enter your credentials for the explorer into the explorer settings and view your files.
ralphmorris's avatar

Hi @edoc,

Thanks for your help on this. That link you provided helped. All I needed was a wildcard at the end of the PutObject as below. It is now working.

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "s3:ListBucket",
                "s3:ListAllMyBuckets",
                "s3:GetBucketLocation"
            ],
            "Resource": [
                "arn:aws:s3:::mmb-dev"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "s3:PutObject*",
                "s3:GetObject",
                "s3:DeleteObject"
            ],
            "Resource": [
                "arn:aws:s3:::mmb-dev/*"
            ]
        }
    ]
}

Thanks @EventFellows for your suggestions too.

2 likes
anas-devhelp's avatar

Here is complete answer for storing image submitted via html form to amazon s3 using laravel

web.php

Route::get('/uploadFileToS3', [ 'as' => 'uploadFileToS3.form', 'uses' => 'UploadFileToS3Controller@Form', ]); Route::post('/uploadFileToS3', [ 'as' => 'uploadFileToS3.submit', 'uses' => 'UploadFileToS3Controller@uploadFileToS3', ]);

.env

AWS_KEY=<YOUR_AWS_KEY> AWS_SECRET=<YOUR_AWS_SECRET> AWS_REGION=<YOUR_AWS_REGION> AWS_BUCKET=<YOUR_AWS_BUCKET>

config/filesystems.php

's3' => [ 'driver' => 's3', 'key' => env('AWS_KEY'), 'secret' => env('AWS_SECRET'), 'region' => env('AWS_REGION'), 'bucket' => env('AWS_BUCKET'), ],

UploadFileToS3Controller.php

namespace App\Http\Controllers; use Illuminate\Http\Request; use Illuminate\Contracts\Filesystem\Filesystem; use Storage;

public function Form(Request $request) { return view('uploadFileToS3'); } public function uploadFileToS3(Request $request) { $image = $request->file('image'); $imageFileName = time() . '.' . $image->getClientOriginalExtension(); // $filepath should be absolute path to a file on disk $filepath = '/microsites/horoscope/images/'.$imageFileName; $bucket = env('AWS_BUCKET'); $keyname = env('AWS_KEY'); $region = env('AWS_REGION'); $s3 = \Storage::disk('s3'); $filePath = '/microsites/horoscope/images/' . $imageFileName; $s3->put($filePath, file_get_contents($image), 'public-read'); dd('File uploaded.....'.Storage::url($filepath));

}

uploadFileToS3.blade.php

{{ csrf_field() }}
anas-devhelp's avatar

$image = $request->file('image'); $imageFileName = time() . '.' . $image->getClientOriginalExtension(); // $filepath should be absolute path to a file on disk $filepath = '/microsites/horoscope/images/'.$imageFileName; $bucket = env('AWS_BUCKET'); $keyname = env('AWS_KEY'); $region = env('AWS_REGION');

    $s3 = \Storage::disk('s3');
    $filePath = '/microsites/horoscope/images/' . $imageFileName;
    $s3->put($filePath, file_get_contents($image), 'public-read');
    dd('File uploaded.....'.Storage::url($filepath));

Please or to participate in this conversation.