11

1and1.com がホストしている Linux サーバーで、何千ものユーザーが何千もの写真をアップロードしています (CentOS を使用していると思いますが、バージョンは不明です)。これは言語に依存しない質問ですが、参考までに、私は PHP を使用しています。

私の最初の考えは、それらをすべて同じディレクトリにダンプすることでしたが、少し前に、ディレクトリにドロップできるファイルまたはディレクトリの数に制限があったことを覚えています。

2 番目に考えたのは、ユーザーの電子メール アドレスに基づいてディレクトリ内のファイルを分割することでした (とにかくユーザー名に使用しているため) が、ディレクトリ内のディレクトリの制限に遭遇したくありません....

とにかく、user@domain.com からの画像については、次のようにします。

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

何千人ものユーザーが「gmail」と言うとしたら、このようにさらに深く掘り下げることができるかもしれません。

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

mike@gmail.com の場合は...

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

これは悪いアプローチですか?他のみんなは何をしているの?ディレクトリが多すぎるという問題にも遭遇したくありません...


関連している:

4

6 に答える 6

28

私は次のことをします:

  1. 入ってきた各画像の MD5 ハッシュを取得します。
  2. これらのことを追跡しているデータベースにその MD5 ハッシュを書き込みます。
  3. MD5 ハッシュ 16 進文字列の最初の数バイトをディレクトリ名として使用するディレクトリ構造にそれらを保存します。したがって、ハッシュが「abcdef1234567890」の場合、「a/b/abcdef1234567890」として保存します。

ハッシュを使用すると、複数回アップロードされた同じ画像をマージすることもできます。

于 2009-05-23T00:28:50.453 に答える
4

ジョーベーダのアプローチを拡張するには:

  • データベース
  • データベース
  • データベース

ユーザー、元のファイル名、アップロード日、写真撮影日(EXIF)などによるファイルのグループ化または検索に関心がある場合は、このメタデータをデータベースに保存し、適切なクエリを使用して適切なファイルを選択します。

データベースのプライマリキー(ファイルハッシュまたは自動インクリメント番号)を使用して、ディレクトリの固定セット内でファイルを検索します(または、ディレクトリごとに固定の最大ファイル数Nを使用し、いっぱいになったら、に移動します。次の写真、たとえば、k番目の写真は{somepath}/aaaaaa/bbbb.jpgaaaaaa = floor(k / N)、10進数または16進数としてフォーマットされ、bbbb = mod(k、N)、10進数または16進数としてフォーマットされた場所に保存する必要があります。あなたのために、のようなものを使用してください{somepath}/aa/bb/cc/dd/ee.jpg

ディレクトリ構造をユーザーに直接公開しないでください。Webブラウザを使用してHTTP経由でサーバーにアクセスしている場合は、www.myserver.com / images / {primary key}のようなURLを指定し、Content-Typeヘッダーに適切なファイルタイプをエンコードします。

于 2009-05-23T00:38:54.053 に答える
3

これがまさにこの状況のた​​めに私がしばらく前に書いた2つの関数です。それらは、それぞれがたくさんのファイルを持っている何千ものメンバーがいるサイトで1年以上使用されています。

本質的には、各メンバーの一意のデータベースIDの最後の桁を使用して、すべてのユーザーに一意のディレクトリを持つディレクトリ構造を計算するという考え方です。最初の数字ではなく最後の数字を使用すると、ディレクトリがより均等に分散されます。メンバーごとに個別のディレクトリがあるということは、メンテナンスタスクがはるかに簡単であることを意味します。さらに、(視覚的に)人々のものがどこにあるかを確認できます。

// 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()は、入力をスクラブして数値を確認するためのサポート関数です。$GLOBALS['site_path']はサーバーの絶対パスです。うまくいけば、そうでなければ彼らは自明になるでしょう。

于 2009-05-23T00:39:00.387 に答える
3

別の要件に使用したものですが、ニーズに合うものは単純な規則を使用することです。

1 ずつ増やして新しい数値の長さを取得し、この数値を前に付けます。

例えば:

「a」は、最後のIDで設定された変数であると仮定します。

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

次に、この規則を使用して、ディレクトリのタイムスタンプを使用できます。

20092305 (yyyymmdd)

次に、次のようにパスを分解できます。

2009/23/05/3565.jpg

(以上)

興味深いのは、日付順と番号順を同時に保持できることです (便利な場合もあります)。パスをより多くのディレクトリに分解することもできます。

于 2009-05-23T00:28:37.863 に答える
2

Joe Beda の答えはほぼ完璧ですが、ラップトップで iirc 2 時間で MD5 が衝突可能であることが証明されていることに注意してください。

とはいえ、実際にファイルの MD5 ハッシュを上記の方法で使用すると、サービスは攻撃に対して脆弱になります。攻撃はどのようになりますか?

  1. ハッカーは特定の写真が気に入らない
  2. 彼は、これがあなたが使用しているプレーンな MD5 であることを確認します (MD5 の image+secret_string は彼を怖がらせる可能性があります)。
  3. 彼は魔法の方法を使って (ここであなたの想像力を使ってください) ハッシュの写真を好きではない写真と衝突させます
  4. 彼はいつものように写真をアップロードします
  5. サービスは古いものを新しいもので上書きし、両方を表示します

誰かが言う:それでは上書きしないでください。次に、誰かが何かをアップロードすることを予測できる場合 (Web で人気のある写真がアップロードされる可能性がある場合)、最初にその「ハッシュ プレース」を取ることができます。ユーザーは、子猫の写真をアップロードすると、実際には次のように見えることに満足するでしょう (ここでは想像力を働かせてください)。私は言います: 10.000 台のコンピューター クラスターによって iirc 127 年でハッキング可能であることが証明されているので、SHA1 を使用しますか?

于 2009-05-23T07:33:54.173 に答える