Man's avatar
Level 2

upload directly to s3

Hello, I am working with an already established code. The image handler uploads the files to a folder in the public uploads directory. see the code below.

    // Lets get all these Arguments and assign them!
    $image = $args['image'];
    $folder = $args['folder'];
    $filename = $args['filename']; 
    $type = $args['type'];

    // Hey if the folder we want to put them in is images. Let's give them a month and year folder
    if($folder == 'images'){
        $month_year = date('FY').'/';
    } else {
        $month_year = '';
    }

    // Check it out! This is the upload folder
    $upload_folder = 'content/uploads/' . $folder . '/'.$month_year;


    if ( @getimagesize($image) ){

        // if the folder doesn't exist then create it.
        if (!file_exists($upload_folder)) {
            mkdir($upload_folder, 0777, true);
        }

        if($type =='upload'){

            $filename =  $image->getClientOriginalName();

            // if the file exists give it a unique name
            while (file_exists($upload_folder.$filename)) {
                $filename =  uniqid() . '-' . $filename;
            }


            $uploadSuccess = $image->move($upload_folder, $filename);

            if(strpos($filename, '.gif') > 0){
                $new_filename = str_replace('.gif', '-animation.gif', $filename);
                copy($upload_folder . $filename, $upload_folder . $new_filename);
            }

        } else if($type = 'url'){
            
            $file = file_get_contents($image);

            if(strpos($image, '.gif') > 0){
                $extension = '-animation.gif';
            } else {
                $extension = '.jpg';
            }


            $filename = $filename . $extension;

            if (file_exists($upload_folder.$filename)) {
                $filename =  uniqid() . '-' . $filename . $extension;
            }

            if(strpos($image, '.gif') > 0){
                file_put_contents($upload_folder.$filename, $file);
                $filename = str_replace('-animation.gif', '.gif', $filename);
            }

            file_put_contents($upload_folder.$filename, $file);

        }
       
    
        $settings = Setting::first();

        $img = Image::make($upload_folder . $filename);

        if($folder == 'images'){
            $img->resize(1280, null, function ($constraint) {
                $constraint->aspectRatio();
            });

            Image::make($upload_folder . $filename)->resize(960, null, function ($constraint) {
                $constraint->aspectRatio();
            })->save($upload_folder . pathinfo($filename, PATHINFO_FILENAME) . '-large.' . pathinfo($filename, PATHINFO_EXTENSION));
            
            Image::make($upload_folder . $filename)->resize(640, null, function ($constraint) {
                $constraint->aspectRatio();
            })->save($upload_folder . pathinfo($filename, PATHINFO_FILENAME) . '-medium.' . pathinfo($filename, PATHINFO_EXTENSION));
            
            Image::make($upload_folder . $filename)->resize(320, null, function ($constraint) {
                $constraint->aspectRatio();
            })->save($upload_folder . pathinfo($filename, PATHINFO_FILENAME) . '-small.' . pathinfo($filename, PATHINFO_EXTENSION));
            
        } else if($folder == 'avatars'){
            $img->resize(300, null, function ($constraint) {
                $constraint->aspectRatio();
            });
        }

        $img->save($upload_folder . $filename);
        
        return $month_year . $filename;

    } else {
        return false;}}</code>

I watched this video https://laracasts.com/series/whats-new-in-laravel-5/episodes/6, and I do not know how to implement this to have the code uploaded directly to s3. How can I make the file upload directly to my s3? I have already set up the filesystem variables.

0 likes
10 replies
rsands's avatar

If you are looking to just pass the file to S3 it can be done as follows

\Storage::disk('s3')->put($filename, file_get_contents($upload_folder . $filename));

First variable is the s3 key, second the local file path.

Or are you looking to have the user upload directly to the bucket? If you are and you want to make thumbs your going to have to create a lambda function to resize the thumbs on s3 directly, otherwise create a storage::disk put for each of the thumbs and main image

1 like
Man's avatar
Level 2

@rsands where do I put that code? on the top of the php code above?

To directly upload all the images and thumbs do I just add storage::disk to the code above? If so, how?

Sorry for all the noob questions, this stuff is not common sense to me yet.

rsands's avatar
rsands
Best Answer
Level 2
 // Lets get all these Arguments and assign them!
    $image = $args['image'];
    $folder = $args['folder'];
    $filename = $args['filename']; 
    $type = $args['type'];

    // Hey if the folder we want to put them in is images. Let's give them a month and year folder
    if($folder == 'images'){
        $month_year = date('FY').'/';
    } else {
        $month_year = '';
    }

    // Check it out! This is the upload folder
    $upload_folder = 'content/uploads/' . $folder . '/'.$month_year;


    if ( @getimagesize($image) ){

        // if the folder doesn't exist then create it.
        if (!file_exists($upload_folder)) {
            mkdir($upload_folder, 0777, true);
        }

        if($type =='upload'){

            $filename =  $image->getClientOriginalName();

            // if the file exists give it a unique name
            while (file_exists($upload_folder.$filename)) {
                $filename =  uniqid() . '-' . $filename;
            }


            $uploadSuccess = $image->move($upload_folder, $filename);

            if(strpos($filename, '.gif') > 0){
                $new_filename = str_replace('.gif', '-animation.gif', $filename);
                copy($upload_folder . $filename, $upload_folder . $new_filename);
            }

        } else if($type = 'url'){
            
            $file = file_get_contents($image);

            if(strpos($image, '.gif') > 0){
                $extension = '-animation.gif';
            } else {
                $extension = '.jpg';
            }


            $filename = $filename . $extension;

            if (file_exists($upload_folder.$filename)) {
                $filename =  uniqid() . '-' . $filename . $extension;
            }

            if(strpos($image, '.gif') > 0){
                file_put_contents($upload_folder.$filename, $file);
                $filename = str_replace('-animation.gif', '.gif', $filename);
            }

            file_put_contents($upload_folder.$filename, $file);

        }
       
    
        $settings = Setting::first();

        $img = Image::make($upload_folder . $filename);

        if($folder == 'images'){
            $img->resize(1280, null, function ($constraint) {
                $constraint->aspectRatio();
            });

            $filename_large = pathinfo($filename, PATHINFO_FILENAME) . '-large.' . pathinfo($filename, PATHINFO_EXTENSION);

            Image::make($upload_folder . $filename)->resize(960, null, function ($constraint) {
                $constraint->aspectRatio();
            })->save($upload_folder . $filename_large);

            \Storage::disk('s3')->put($filename_large, file_get_contents($upload_folder . $filename_large));
            
            $filename_medium = pathinfo($filename, PATHINFO_FILENAME) . '-medium.' . pathinfo($filename, PATHINFO_EXTENSION);

            Image::make($upload_folder . $filename)->resize(640, null, function ($constraint) {
                $constraint->aspectRatio();
            })->save($upload_folder . $filename_medium);

            \Storage::disk('s3')->put($filename_medium, file_get_contents($upload_folder . $filename_medium));

            $filename_small = pathinfo($filename, PATHINFO_FILENAME) . '-small.' . pathinfo($filename, PATHINFO_EXTENSION);
            
            Image::make($upload_folder . $filename)->resize(320, null, function ($constraint) {
                $constraint->aspectRatio();
            })->save($upload_folder . $filename_small);

            \Storage::disk('s3')->put($filename_small, file_get_contents($upload_folder . $filename_small));
            
        } else if($folder == 'avatars'){
            $img->resize(300, null, function ($constraint) {
                $constraint->aspectRatio();
            });
        }

        $img->save($upload_folder . $filename);
        
        \Storage::disk('s3')->put($filename, file_get_contents($upload_folder . $filename));

        return $month_year . $filename;

    } else {
        return false;}}</code>
1 like
rsands's avatar

Its not a great looking piece of code but it should work. After any image save() call you can simply put the storage disk put call. It will put it onto the bucket in the root path with the same filename as you set.

Ideally you would put a check on the s3 call to then unlink() the local file as it would no longer be needed - just to tidy up and not load the storage for no reason.

But really you could tidy it up further with an array foreach() - loop through array of resize sizes you want

1 like
Man's avatar
Level 2

@rsands Wow, I never got a email notification for your answer. Thank you. I was able to upload to s3 bucket with your code. How do I keep the file structure and unlink from local?

Man's avatar
Level 2

@rsands I figured out how to change the file structure. Now all I have to do is unlink and delete the local file.

Man's avatar
Level 2

I figured that out too. All I had to do was use unlink($filename) on each put command. Thanks again for all your help.

rsands's avatar

@Man Sorry i too missed your replying to this thread. You are correct unlink().

Make sure you handle any errors of the file not existing :)

Please or to participate in this conversation.