tornadofay's avatar

search database for files linked in public storage

Well Met,

I have table in database that is like that

Schema::create('factory_health_certificates',........... $table->increments('id'); $table->uuid('factory_id'); $table->string('cert_image_path'); ...

in column 'cert_image_path' i save path to image uploaded to public storage like that

class FactoryHealthCertificate extends Model
.
.
//get current datetime
$mytime = Carbon::now();

//get the file
$file = $request->file('cert_image_path');

    if($file  != null)
    {
        if (in_array($file->getClientMimeType(), 
                        ['image/gif', 'image/jpeg', 'image/pjpeg', 'image/png']) 
                && $file->getClientSize() <= 204800
                && ! $file->getError()
                && $file->isValid()) 
        {
    //hash file name with datetime
    $md5Name = md5_file($request->file('cert_image_path')
            ->getRealPath()) . $mytime
            ->format('d.m.Y.H.i.s');

    //get extensions 
        $guessExtension = $request->file('cert_image_path')->guessExtension();

    //path to save
        $save_file_path = 'images/Factory/'. $request
            ->factory_id . '/health_certificate_images/';

    //save extension
        $save_file_name = $md5Name . '.' . $guessExtension;

    // Upload file to path
        $file = $request->file('cert_image_path')
            ->storeAs($save_file_path , $save_file_name ,'public');
          
    //path saved to database
        $this->cert_image_path = $save_file_path . $save_file_name;

    //setting factory id for relations
    $this->factory_id = $request->factory_id;
    
    //saving to database
    $this->save();

So in the end in public storage i have folder "Factory" that conatins folders named on "factory_id" => UUID so every factory have 1 main folder and inside that folder i have other folder for each file type in this example the folder name is "health_certificate_images" and inside that folder is the files uploaded of that type and this files have "hashname + datetime.ext" in summry it look like this : "\public\storage\images\Factory\78c0fad3-1818-49c4-9fb7-751c9dba66f7\health_certificate_images\2671072fc19eb479c5959073f37d884614.07.2018.09.15.39.jpeg"

I want to have option in the web site dashboard that search the public storage foreach file and check if that file does NOT exists in the database then it deletes it if it exist it leave it and move to check the next file.

btw this is just small example of many more files for Factories and Companies data and this data is important to keep it safe

so my questions are 1-how can i search public storage like that ? 2- foreach file i will need to perform query on database that involves UUID , what is the most efficient way to do that ? 3- do you see any problem with this approach ?

thank you for your help and time.

0 likes
3 replies
bobbybouwmann's avatar

Well you can search based on the path right? So you loop over all files you have in the storage/images directory. After that you can use explode to determine each part of the file and then based on that query the database. If the file doesn't exist in the database anymore you can delete it. I think that's the easiest way.

tornadofay's avatar

I'm sorry i didn't mention i'm new to laravel and php, just started learning laravel about 2 months ago and that is my first project with it, i have experience in desktop development c# but that is different.

so is it should be like that:

foreach (\Illuminate\Support\Facades\Storage::folders('Factory') as $factoryfolder) {
    foreach (\Illuminate\Support\Facades\Storage::folders($factoryfolder) as $typefolder) {
            foreach (\Illuminate\Support\Facades\Storage::files($typefolder) as $filename) {
$file = \Illuminate\Support\Facades\Storage::get($filename);
// do whatever with $file;
        }
    }
}

if i have like 1000 factories and each factory have at least 5 file types folder and each folder have at least 3 files(images or pdf) this loop would take ages to finish, is that right ? also wouldn't that cause problem with the db server that's like 15000 search query

tornadofay's avatar

So i have another idea but i'm not sure if it is better or not, what if i made it like when every "Factory" user 'update' or 'delete' file type i search this directory and clean it up ?

this way instead of looping on many folders and files at once, the Model will have clean up function that fires when this column data changes on update and delete ?

is this better approach ? and is it safe ? what if two factories with different uuid updating same Model at the same time will that cause any problems or make any unwanted behavior ? I really don't know and I want to know best practices when dealing with situation like this.

Please or to participate in this conversation.