bbmrw's avatar
Level 1

Problem with uploading private images in Laravel

I have two inputs with type file on page. First input uploads images that are visible to user and that is the one that works. Second one is supposed to upload private images that user can't see and I am having trouble uploading them. I don't know if I am supposed to copy code from first input and change it a bit and put other post route or if there is some shorter way. I have private column (booleand) in photos table that shows if the image is private or not. Any ideas or help on code is appreciated. Here is my code.

index.blade.php

<div class="row">

    //PUBLIC
    <div class="col-lg-6 col-md-6 col-12">
        <article class="publicImgs">
            <div class="uploadedImages flex">
                @foreach($photos as $photo)
                    <div class="singleImg">
                        <div class="imgWrap js-privateImg" data-slider="7">
                            <img class="img-responsive" src="<?php echo \App\User::CDNprofilePhoto($photo->image, 'cdn') ?>" alt="">
                        </div>
                        <i class="fas fa-trash-alt deleteImg"></i>
                    </div>
                @endforeach
            </div>
            <div class="dropzone"></div>
            @if(!empty($photos))
                <form action="{{ route('photos.store') }}" class="photo-upload" enctype="multipart/form-data" method="POST" id="imageUploadForm">
                    @csrf
                        <input id="uploadPublicImg" type="file" name="thumb">
                        <button class="uploadImgBtn baseBtn" name="">UPLOAD PUBLIC</button>
                </form>
            @endif
        </article>
    </div>


    // PRIVATE
    <div class="col-lg-6 col-md-6 col-12">
        <article class="privateImgs">
            <div class="uploadedImages flex">
                @for ($i = 0; $i < 3; $i++)
                    <div class="singleImg">
                        <div class="imgWrap js-privateImg" data-order="{{$i}}" data-slider="7">
                            <img src="https://coderwall-assets-0.s3.amazonaws.com/uploads/1826/ffffff.png" alt="">
                        </div>
                        <i class="fas fa-trash-alt deleteImg"></i>
                    </div>
                @endfor
            </div>
            <div class="dropzone"></div>
            <button class="uploadImgBtn baseBtn">
                <label for="uploadPublicImg">UPLOAD PRIVATE</label>
                <input id="uploadPublicImg" type="file">
            </button>
        </article>
    </div>
</div>

PhotoUpload.php

<?php

namespace App;

use Intervention\Image\Facades\Image;
use Illuminate\Support\Facades\Config;
use Illuminate\Database\Eloquent\Model;

class PhotoUpload extends Model
{
    # Max file size
    private static $byteSizeLimit = 5242880; // 5 MB

    # Image quality settings
    private static $iconQuality;
    private static $profileQuality;
    private static $galleryQuality;
    private static $fullQuality;

    public static function validate($fileData)
    {
        $fileSize = $fileData->getSize();
        $mimeType = $fileData->getMimeType();

        if ($fileSize > static::$byteSizeLimit) {
            return FALSE;
        }

        if (!in_array($mimeType, ['image/jpeg', 'image/png', 'image/gif'])) {
            return FALSE;
        }

        return TRUE;
    }

    public static function upload($userId, $imageData, $userUploaded = TRUE)
    {
        static::loadDefaults();

        if ($userUploaded) {
            $imgFile = $imageData['file'];
            $fileExt = $imgFile->getClientOriginalExtension();
            $mimeType = $imgFile->getMimeType();
        } else {
            $imgFile = public_path().'/'.$imageData['image'];
            $fileExt = $imageData['fileExt'];
            $mimeType = $imageData['mime'];
        }

        # Set filaname suffix/extensions
        $rand = mt_rand(999, 999999);
        $origExt = '_'.$rand.'.'.$fileExt;
        $profileExt = '_p.'.$fileExt;
        $iconExt = '_i.'.$fileExt;
        $galleryExt = '_'.$rand.'_g.'.$fileExt;

        # Set filenames
        $newFilename = $userId.'_'.md5(uniqid());
        $fullsizeFilename = $newFilename.$origExt;

        $photoDir = 'assets/photos/upload_'.mt_rand(1, 99).'/';
        $fileDir = public_path().'/'.$photoDir;
        # If directory doesn't exist, create it.
        if (! file_exists($fileDir)) {
            mkdir($fileDir, 0775, TRUE);
        }

        # Save the original photo
        Image::make($imgFile)
            ->orientate()
            ->save($fileDir.$fullsizeFilename, static::$fullQuality);

        $photoData = [
            'directory'   => $photoDir,
            'filename'    => $newFilename,
            'orig_ext'    => $origExt,
            'gallery_ext' => $galleryExt,
            'profile_ext' => $profileExt,
            'icon_ext'    => $iconExt,
            'mime'        => $mimeType
        ];

        return $photoData;
    }

    private static function loadDefaults()
    {
        # Image quality settings
        $quality = Config::get('photo.quality');
        static::$iconQuality = $quality['icon'];
        static::$profileQuality = $quality['profile'];
        static::$galleryQuality = $quality['gallery'];
        static::$fullQuality = $quality['full_size'];
    }
}

PhotoController.php

<?php

namespace App\Http\Controllers;

use App\User;
use App\Photo;
use App\PhotoUpload;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Auth;

class PhotoController extends Controller
{
    public function store(Request $request)
    {
        $userId = $request->input('user_id') ? $request->input('user_id') : Auth::user()->id;
       
        
        return $this->upload($request);  
    }

    public function destroy($photoId, $userId)
    {
        $user = User::find($userId);
        if ($user->photo_id === '$photoId') {
            $replacementPhoto = DB::table('photos')
                ->where('userId', $userId)
                ->where('private', '!=', true)
                ->pluck('id');

            if (isset($replacementPhoto)) {
                $user->photo_id = $replacementPhoto;
            } else {
                $user->photo_id = 0;
            }
            $user->save();
        }

        $photo = Photo::find($photoId);
        if (isset($photo)) {
            $photoDir = $photo->directory;
            $filename = $photo->filename;
            $filePath = public_path() . '/' . $photoDir . $filename;
            $origImage = $filePath . $photo->orig_ext;
            $galleryImage = $filePath . $photo->gallery_ext;
            $profileImage = $filePath . $photo->profile_ext;
            $iconImage = $filePath . $photo->icon_ext;

            # Remove the image files from the server.
            if(file_exists($origImage)){
                unlink($origImage);
            }
            if(file_exists($galleryImage)){
                unlink($galleryImage);
            }
            if(file_exists($profileImage)){
                unlink($profileImage);
            }
            if(file_exists($iconImage)){
                unlink($iconImage);
            }

            # Delete the photo from the database
            $photo->delete();
        }

        return redirect()->back();
    }

    public function photoPrivacy($pid, $privacy, $userId)
    {
        $photo = Photo::find($pid);
        $photo->private = $privacy;
        $photo->save();

        return redirect()->back();
    }

    private function upload(Request $request)
    {
        $userId = Auth::user()->id;
        $file = $request->file('thumb');

        if (!empty($file)) {
            $imageData = [
                'file' => $file
            ];

            $validate = PhotoUpload::validate($file, TRUE);
            
            if (!$validate) {
                return redirect()->back()->withInput();
            }

            # Upload image files
            $upload = PhotoUpload::upload($userId, $imageData, TRUE);

            # Add to 'photos' table.
            $photo = new Photo();
            $private = FALSE;
            $mainPhoto = FALSE;

            # Insert photo into db
            $photoId = $photo->addPhoto($userId, $upload, $private);
            if (isset($photoId)) {
                # Set photo as the default profile photo, if user doesn't have one already.
                $user = User::find($userId);
                if ($user->photo_id === '0') {
                    $user->photo_id = $photoId;
                    $user->save();
                }

                $response =  [
                    "message"   => "Your photo has been uploaded succesfully.",
                    "error"     => false
                ];

                return json_encode($response);
            }
        }
        $response =  [
            "message"   => "There was a problem adding your photo. Please try again.",
            "error"     => true
        ];

        return json_encode($response);
    }
}
0 likes
4 replies
Snapey's avatar

As a first step make sure both file input fields have name= attributes

bbmrw's avatar
Level 1

@snapey

Yes, i forgot that. But that is small problem :) How should I proceed later?

Snapey's avatar

You seem to have written a lot of code, yet missed one of the most fundamental points. Suggest you build it step by step ensuring you get what you expected at each stage

Please or to participate in this conversation.