Tysiące zdjęć, jak zorganizować strukturę katalogów? (linux)

Dostaję tysiące zdjęć przesłanych przez tysiące użytkowników na moim serwerze Linux, który jest hostowany przez 1and1.com (wierzę, że używają CentOS, ale nie jestem pewien wersji). Jest to pytanie agnostyczne w języku, jednak w celach informacyjnych używam PHP.

Moją pierwszą myślą było po prostu wrzucić je wszystkie do tego samego katalogu, jednak, pamiętam jakiś czas temu, był limit ile plików lub katalogów można upuścić w katalogu.

Moja druga myśl było partycjonowanie plików wewnątrz katalogów na podstawie adresu e-mail użytkownika (jak to jest to, czego używam do nazwy użytkownika tak czy inaczej), ale nie chcę uruchomić do limitu dla katalogów w katalogu....

W każdym razie, dla zdjęć z [email protected], miałem to zrobić:

/images/domain.com/user/images...

Czy to mądre zrobić, co jeśli tysiące użytkowników mają powiedzieć 'gmail' może mógłbym nawet pójść głębiej, jak to

/images/domain.com/[first letter of user name]/user/images...

Więc dla [email protected] byłoby...

/images/domain.com/m/mike/images...

Czy to źle podejście? Co robią inni? Nie chcę również napotkać problemów ze zbyt dużą ilością katalogów...


Powiązane:

Author: Community, 2009-05-23

6 answers

Wykonałbym:

  1. Weź Skrót MD5 każdego obrazu, gdy się pojawi.
  2. Napisz, że MD5 hash w bazie danych, w której śledzisz te rzeczy.
  3. przechowuj je w strukturze katalogów, gdzie jako nazwę katalogu używasz pierwszych kilku bajtów ciągu sześciokątnego MD5. Jeśli więc hash to 'abcdef1234567890', zapisałbyś go jako 'A/b / abcdef1234567890'.

Użycie skrótu pozwala również scalić ten sam obraz przesłany wiele razy.

 27
Author: Joe Beda,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-05-23 00:28:50

Aby rozszerzyć podejście Joe Beda:

  • baza danych
  • baza danych
  • baza danych

Jeśli zależy ci na grupowaniu lub znajdowaniu plików według użytkownika, oryginalnej nazwy pliku, daty przesłania, daty zrobienia zdjęcia (EXIF) itp., przechowuj te metadane w bazie danych i korzystaj z odpowiednich zapytań, aby wybrać odpowiednie pliki.

Użyj klucza podstawowego bazy danych - czy to hash pliku, czy numer autoincrementujący - aby zlokalizować pliki między ustalonym zestawem katalogów (alternatywnie, użyj stałej maksymalnej liczby plików N na katalog, a po wypełnieniu przejdź do następnego, np. Kth zdjęcie powinno być przechowywane w {somepath}/aaaaaa/bbbb.jpg gdzie aaaaaa = floor (k / N), sformatowane jako decimal lub hex, i bbbb = mod(k,N), sformatowane jako decimal lub hex. Jeśli to dla Ciebie zbyt płaska hierarchia, użyj czegoś w rodzaju {somepath}/aa/bb/cc/dd/ee.jpg)

Nie ujawniaj struktury katalogów bezpośrednio użytkownikom. Jeśli używają przeglądarek internetowych, aby uzyskać dostęp do serwera przez HTTP, podaj im adres URL, taki jak www.myserver.com/images/{klucz podstawowy} i zakodować właściwy typ pliku w nagłówku Content-Type.

 4
Author: Jason S,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-05-23 00:48:25

Oto dwie funkcje, które napisałem jakiś czas temu Dla dokładnie tej sytuacji. Są one używane od ponad roku na stronie z tysiącami członków, z których każdy ma wiele plików.

Zasadniczo chodzi o to, aby użyć ostatnich cyfr unikalnego identyfikatora bazy danych każdego członka do obliczenia struktury katalogów, z unikalnym katalogiem dla każdego. Użycie ostatnich cyfr, a nie pierwszych, zapewnia bardziej równomierne rozłożenie katalogów. Osobny katalog dla każdego członka oznacza utrzymanie zadania są o wiele prostsze, dodatkowo możesz zobaczyć, gdzie są rzeczy ludzi (jak wizualnie).

// checks for member-directories & creates them if required
function member_dirs($user_id) {

    $user_id = sanitize_var($user_id);

    $last_pos = strlen($user_id);
    $dir_1_pos = $last_pos - 1;
    $dir_2_pos = $last_pos - 2;
    $dir_3_pos = $last_pos - 3;

    $dir_1 = substr($user_id, $dir_1_pos, $last_pos);
    $dir_2 = substr($user_id, $dir_2_pos, $last_pos);
    $dir_3 = substr($user_id, $dir_3_pos, $last_pos);

    $user_dir[0] = $GLOBALS['site_path'] . "files/members/" . $dir_1 . "/";
    $user_dir[1] = $user_dir[0] . $dir_2 . "/";
    $user_dir[2] = $user_dir[1] . $dir_3 . "/";
    $user_dir[3] = $user_dir[2] . $user_id . "/";
    $user_dir[4] = $user_dir[3] . "sml/";
    $user_dir[5] = $user_dir[3] . "lrg/";

    foreach ($user_dir as $this_dir) {
        if (!is_dir($this_dir)) { // directory doesn't exist
            if (!mkdir($this_dir, 0777)) { // attempt to make it with read, write, execute permissions
                return false; // bug out if it can't be created
            }
        }
    }

    // if we've got to here all directories exist or have been created so all good
    return true;

}

// accompanying function to above
function make_path_from_id($user_id) {

    $user_id = sanitize_var($user_id);

    $last_pos = strlen($user_id);
    $dir_1_pos = $last_pos - 1;
    $dir_2_pos = $last_pos - 2;
    $dir_3_pos = $last_pos - 3;

    $dir_1 = substr($user_id, $dir_1_pos, $last_pos);
    $dir_2 = substr($user_id, $dir_2_pos, $last_pos);
    $dir_3 = substr($user_id, $dir_3_pos, $last_pos);

    $user_path = "files/members/" . $dir_1 . "/" . $dir_2 . "/" . $dir_3 . "/" . $user_id . "/";
    return $user_path;

}

Sanitize_var() jest funkcją pomocniczą do szorowania danych wejściowych i zapewnienia, że są numeryczne, $GLOBALS ['site_path'] jest absolutną ścieżką dla serwera. Miejmy nadzieję, że nie będą wyjaśniać inaczej.

 3
Author: da5id,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-05-23 00:51:04

To, czego użyłem do innego wymogu, ale który może pasować do Twoich potrzeb, to użycie prostej konwencji.

Zwiększ o 1 i uzyskaj długość nowej liczby, a następnie prefiks z tą liczbą.

Na przykład:

Załóżmy, że' a ' jest var ustawionym z ostatnim id.

a = 564;
++a;
prefix = length(a);
id = prefix + a; // 3565

Następnie możesz użyć znacznika czasu dla katalogu, używając tej konwencji:

20092305 (yyyymmdd)

Wtedy możesz eksplodować swoją ścieżkę w ten sposób:

2009/23/05/3565.jpg

(lub więcej)

To ciekawe ponieważ można zachować kolejność sortowania według daty i numeru w tym samym czasie (czasami przydatne) I nadal możesz rozłożyć swoją ścieżkę w większej liczbie katalogów

 3
Author: Boris Guéry,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-12-02 20:09:14

Odpowiedź Joe Beda jest prawie idealna, ale proszę pamiętać, że MD5 udowodniono, że można go zderzyć w iirc 2 godziny na laptopie?

To powiedziawszy, jeśli rzeczywiście użyjesz skrótu MD5 pliku w opisany sposób, Twoja usługa stanie się podatna na ataki. Jak będzie wyglądał atak?

  1. haker nie lubi konkretnego zdjęcia
  2. zapewnia, że jest to zwykły MD5, którego używasz (MD5 obrazu+secret_string może go wystraszyć)
  3. używa magii metoda zderzenia zdjęcia (użyj wyobraźni tutaj) hasha ze zdjęciem, które mu się nie podoba
  4. wgrywa zdjęcie tak, jak normalnie by to zrobił
  5. Twój serwis zastępuje stary z nowym i wyświetla oba

Ktoś mówi: nie nadpisujmy go wtedy. Następnie, jeśli można przewidzieć, że ktoś coś załaduje (np. popularne zdjęcie w sieci może zostać przesłane), można najpierw zająć" hash-place " tego. Użytkownik byłby zadowolony, gdy przesyłając zdjęcie kotka, stwierdziłby, że faktycznie pojawia się jako (użyj wyobraźni tutaj). Mówię: użyj SHA1, ponieważ udowodniono, że można go zhakować w iirc 127 lat przez klaster 10.000 komputerów?

 2
Author: Paweł Polewicz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-05-23 07:33:54

Może się spóźnić na mecz. Ale jednym z rozwiązań (jeśli pasuje do twojego przypadku użycia) może być hashowanie nazw plików. Jest to sposób na stworzenie łatwej do odtworzenia ścieżki do pliku przy użyciu nazwy pliku, jednocześnie tworząc dobrze rozproszoną strukturę katalogów. Na przykład, możesz użyć bajtów hashcode nazwy pliku jako ścieżki:

String fileName = "cat.gif";
int hash = fileName.hashCode();
int mask = 255;
int firstDir = hash & mask;
int secondDir = (hash >> 8) & mask;

Spowoduje to, że ścieżka będzie:

/172/029/cat.gif

Możesz następnie znaleźć cat.gif w strukturze katalogów, odtwarzając algorytm.

Użycie HEX jako nazw katalogów byłoby tak proste, jak Konwersja wartości int:

String path = new StringBuilder(File.separator)
        .append(String.format("%02x", firstDir))
        .append(File.separator)
        .append(String.format("%02x", secondDir)
        .toString();

W wyniku:

/AC/1D/cat.gif

Napisałem artykuł o tym kilka lat temu, a ostatnio przeniosłem go do Medium. Zawiera kilka szczegółów i przykładowy kod: nazwa pliku Hashing: Tworzenie zaszyfrowanej struktury katalogów . Mam nadzieję, że to pomoże!

 0
Author: Michael Andrews,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-06-27 19:03:51