Connect with us

Upload files to Amazon S3 from the browser using pre-signed post (Laravel, Vue.js/Nuxt.js)

kizinho

Published

on

Follow
DEVELOPER PROGRAMMING: Upload files to Amazon S3 from the browser using pre-signed post (Laravel, Vue.js/Nuxt.js) [New  Developer Programming] » Naijacrawl
Photo: Naijacrawl
site

Upload files to Amazon S3 from the browser using pre-signed post (Laravel, Vue.js/Nuxt.js)

This article was written by Okonkwo Buchi Flair a ccolleague of mind, read and know how to simply upload your files via Amazon S3.

original article can be found here

Before I begin I would love to point out that is my first post so please pardon me any errors you may find as you read along


Recently I’ve been working on a e-learning platform which of course was going to deal with a lot of uploads and letting the server handle all that will be quite… 😫 And so I had to find an alternative which was direct uploads from the browser. I hit Google search and boy! there were tons of info but then they all made use of javascript, the ones with php used html forms. However, in this post we won’t be using html form. we’ll be making use of axios.

This post assumes you’ve set up your s3 bucket and is fully focused on how to get your uploads working. Don’t forget your CORS configuration as well.


First add your bucket details to your .env file and don’t forget to restart when you make changes to your .env file

AWS_ACCESS_KEY_ID=xxxxxxV2HQFVM
AWS_SECRET_ACCESS_KEY=xxxxxx+xxxx+xxxx+xxxxx
AWS_DEFAULT_REGION=eu-west-2
AWS_BUCKET=Your-Bucket-Name

Next install aws sdk by running the following code

composer require aws/aws-sdk-php-laravel

Create a controller that’s going to take care of your uploads. Meanwhile the filesystem configuration file located at config/filesystem.php is already set up by default to help you access your S3 configurations in the .env file

use Aws\S3\PostObjectV4;
use Aws\S3\S3Client;

class MyController extends Controller
{
public function upload(Request $request)
{
$filename =  $request->filename;
$directory =  $request->directory;
$s3 = config('filesystems.disks.s3');
$client = new S3Client(['version' => 'latest','region' => $s3['region'],'credentials' => ['key' => $s3['key'],'secret' => $s3['secret'],
]]);
$bucket = $s3['bucket'];
$prefix = $directory . '/';
$acl = 'public-read';
$expires = '+10 minutes';
$formInputs = [
 'acl' => $acl,
 'key' => $prefix . $filename,
];
$options = [
 ['acl' => $acl],
 ['bucket' => $bucket],
 ['starts-with', '$key', $prefix],
];
$postObject = new PostObjectV4($client, $bucket, $formInputs, $options, $expires);
$attributes = $postObject->getFormAttributes();
$inputs = $postObject->getFormInputs();
return response(['attributes' => $attributes, 'inputs' => $inputs, 'url' => $attributes['action'] . '/' . $directory . '/' . $filename]);
}
}

So let me explain what’s happening in the above code. From my frontend I am going to make a post request which would contain the name of the file (just as it would be in my s3 bucket and also the folder where it’s going to be saved since my files are going to be saved in different folders. I get my s3 configurations from the env file use s3 file configuration in the config/filesystem.php file. The rest are self explanatory I hope. The $attributes contains information like the form action which is going to look like https://your-bucket-url. Yours won’t necessary have a directory of course. The ‘url’ in my return is what I intend to save in my database once my upload is successful and it would look like this https://bucket-url/directory/filename. With this you will be able successfully generate a presigned POST.

Next create a post route that points to the controller. Since I am making use of Lumen my route looks like this

$router->post(‘uploads/store’, ‘[email protected]’);

Next we’ll dive into the frontend part where we’ll be submitting a form with the detailed generated above.

In my Nuxt file I created a component S3FileUploads.vue that looked like this

I am going to attach screenshots instead for some codes.

I have a computed property which basically returns the file extension

computed property get file extension

I also have a method for generating random strings

random string generator

I like to have a general file or files where my endpoints are. It makes it easier to make changes. So I have an endpoint which points to the controller that generates the presigned post for me.

And then I have my upload file method. The first part of this method involved me trying to generate a unique name for my files and

There was an issue I encountered while trying send the file to my s3 with axios. My header already contained an Authorization token which made the s3 reject the request, and I couldn’t remove the Authorization because of course I can’t access the backend if my request doesn’t contain the token. So removing it wasn’t an option. Th alternative for me was to use the fetch

Of course there were other things I did like store the file url to the database if the upload was successful. That’s basically it. Feel free to ask any questions, I’ll try to reply them, and I’d really appreciate those claps too. Thanks for reading

site


kizinho

I am a software developer, like meeting people and love blogging, that's why I developed naijacrawl because that's what I love doing.

Continue Reading
Click To Comment

BE First To Comment


    Leave a Reply

    Your email address will not be published. Required fields are marked *

    Laravel 6 and 7 Package for Paystack

    kizinho

    Published

    on

    NEWS: Laravel  6 and  7 Package for Paystack [New  Developer] » Naijacrawl
    Photo: Naijacrawl

    Hi, Folks since the release of laravel version 6 and 7, it is very difficult to easily use Paystack on it due to lack of maintenance but today unicodeveloper of the package have taken his time to release a new update on the package.

    To use it, you just need to follow the same pattern we normally do and get things working back again.

    Visit the package URL here


    Continue Reading

    How to solve This page isn’t working HTTP ERROR 500 in Laravel

    kizinho

    Published

    on

    DEVELOPER PROGRAMMING: How to solve This page isn’t working HTTP ERROR 500 in Laravel [New  Developer Programming] » Naijacrawl
    Photo: Naijacrawl

    In case you ran into this problem This page isn’t working www.example.com is currently unable to handle this request HTTP ERROR here is the cause and how to fix it. First, it must not be an error from your code, it is an error from querying large data from your database. So request ran out of memory, to fix it follow this step.

    In your Laravel root project folder locate this file

    vendor/laravel/framework/src/Illuminate/
    Database/Connection.php.
    

    Insert this line of code after line 324 

    ini_set('memory_limit', '-1'); 
    

    or follow the code snippet or image below:


     public function select($query, $bindings = [], $useReadPdo = true)    {        return $this->run($query, $bindings, function ($query, $bindings) use ($useReadPdo) {            if ($this->pretending()) {                return [];            }            // For select statements, we'll simply execute the query and return an array            // of the database result set. Each element in the array will be a single            // row from the database table, and will either be an array or objects.            ini_set('memory_limit', '-1');         
    
       $statement = $this->prepared($this->getPdoForSelect($useReadPdo)                              ->prepare($query));            $this->bindValues($statement, $this->prepareBindings($bindings));            $statement->execute();            return $statement->fetchAll();        });    }
    


    Continue Reading

    Laravel 7 comes with Easy Implicit Route Model Binding

    kizinho

    Published

    on

    NEWS: Laravel 7 comes with Easy Implicit Route Model Binding [New  Developer] » Naijacrawl
    Photo: Naijacrawl

    Laravel 7 will be out 2020 with new awesome features. You can clean the way routing is been done with one line of code.

    But you can try the dev version by running this code

    laravel new example --dev
    


    In laravel 7 you can bind routes like this:


    Route::get('/posts/{post:slug}', function (Post $post) {
        // ...
    });
    
    


    Currently, Laravel 6 and below requires you to define a getRouteKeyName() method on the model like so:

    <?php
    
    class Post extends Model
    {
        /**
         * Get the route key for the model.
         *
         * @return string
         */
        public function getRouteKeyName()
        {
            return 'slug';
        }
    }
    


    You can use the below route binding when you have multiple routes that you want to bind differently.

    For example, the frontend route uses slugs to display posts and backend admin uses ids to manage posts:


    Route::get('/posts/{post:slug}', function (Post $post) {
        // ...
    });
    
    // Or you could use the default `{post}` here...
    Route::get('/admin/posts/{post:id}/edit', function (Post $post) {
        // ...
    });
    


    Thanks for reading.



    Continue Reading

    Latest