Question: How is the best way to store files linked with a database where not too many files are stored in the same directory (slowing down FTP browsing etc)

My own proposal:

```
3000000/0/70000/9000/100/30/3079138.full.pdf
3000000/0/70000/9000/100/30/3079138.thumb.png
3000000/0/70000/8000/900/20/3078928.full.png
3000000/0/70000/8000/900/20/3078928.thumb.pdf
3000000/0/70000/8000/900/20/3078929.full.pdf
3000000/0/70000/8000/900/20/3078929.thumb.png

```

Answer: 
With this solution there will always be a maximum of 10 files (id's) in each directory

With files (id's) ranging from 1 to 1999 the directories in the root will look like this:
![enter image description here](https://i.stack.imgur.com/a5Mxh.png)

create path for an ID
=====================

```
require_once 'File_structure.php';    
for($i=1; $i<2000; $i++){
    $File = new File_structure();
    $File->id = $i;
    $File->prepend_path = 'image/';
    $path = $File->create();
    file_put_contents($path.$i, 'sd');
}

```

get path for an ID
==================

```
require_once 'File_structure.php';
$id = 1254;
$File = new File_structure();
$File->id = $id;
$File->prepend_path = 'image/';
$path = $File->get();
if(is_file($path.$id)){
    echo 'ok';
}

```

class
=====

```
class File_structure {
    public $id;
    public $prepend_path = '';

    private $path = array();

    function get(){
        $this->path();

        return $this->prepend_path.(substr($this->prepend_path, -1) == '/' ? '':'/').implode('/', $this->path).'/';
    }

    function create(){
        $this->path();

        $path = substr($this->prepend_path, -1) == '/' ? substr($this->prepend_path, 0, -1):$this->prepend_path;
        foreach($this->path as $dir){
            $path .= '/'.$dir;
            if(!is_dir($path)){
                mkdir($path);
                chmod($path, 0777);
            }
        }

        return $path.'/';
    }

    function path(){
        $this->prepare_id();

        $length = strlen($this->id);
        for($i=0; $i<$length; $i++){
            $len = $length - $i;
            if($len <= 1){
                break;
            }
            if($path = (int)str_pad($this->id[$i], $len, 0, STR_PAD_RIGHT)){
                $this->path[] = $path;
            }
        }
    }

    function prepare_id(){
        $this->id = (string)$this->id;
    }
}

```
Usually i store files based on a simple pattern thats easy to work with:

```
uploads/<year>/<month>/<day>/full.pdf
uploads/<year>/<month>/<day>/thumb.png

```

where i naturally check for filename collisions and correct them