次のデータベース構造を使用することをお勧めします。

テーブルFile
には少なくとも次のものがあります。

IDFile
auto_increment
列/主キーです
。外部キーですUserID
。nullable
FK_File_User
私が提案するのは:
ON UPDATE NO ACTION -- IDUser is auto_increment too. No changes need to be tracked.
ON DELETE SET NULL -- If user deleted, then File is not owned. Might be deleted
-- with CRON job or something else.
それでも、別の列がFile
テーブルに追加される場合があります。
- 実際のアップロード日時
- 実際の MIME タイプ
- 実際の保管場所 (分散ストレージ システムの場合)
- ダウンロード数 (別の表の方が適切な解決策になる場合があります)
等...
いくつかの利点:
- 1 回のデータベース操作で取得できるため、ファイル サイズ、ハッシュ、拡張子、またはファイル メタを計算する必要はありません。
File
各ユーザーのファイル数/使用スペース/テーブルに書き込んだものの統計を単一のSELECT ... GROUP BY ... WITH ROLLUP
ステートメントで取得でき、複数のストレージデバイスに分散している可能性のある実際のファイルの分析よりも高速です。
- さまざまなユーザーにファイル アクセス許可を適用できます。テーブル構造データベースの大幅な変更には費用がかかりません。
次の 2 つの理由から、保存時に元のファイル名が必要であるというオプションは考慮しません。
- ファイルには、キリル文字など、サーバー OS ファイルシステムで正しくサポートされていない名前が付いている場合があります。
- 2 つの異なるファイルが完全に同一の名前を持つ場合があるため、そのうちの 1 つが別のファイルによって上書きされる可能性があります。
したがって、解決策があります:
IDFile
1) ファイルがテーブルからアップロードされるときにファイルの名前を変更INSERT
しFile
ます。安全で、重複はありません。
2) ファイルが必要になったときやダウンロードされたときに、次のようにファイルの名前を復元します。
// peform query to "File" table by given ID
list($name, $ext, $size, $md5) = $result->fetch_row();
$result->free();
header('Content-Length: ' . $size);
header('Content-MD5: ' . $md5);
header('Accept-Ranges: bytes');
header('Connection: close');
header('Content-Type: application/force-download');
header('Content-Disposition: attachment; filename="' . $name . '.' . $ext . '"');
// flush file content
3)実際のファイルは、単一のディレクトリ(IDFile
安全であるため)およびIDUser
-名前付きのサブディレクトリ-状況に応じて保存される場合があります。
4)IDFile
直接シーケンスと同様に、ファイルの一部が失われた場合、実際のファイル名シーケンスの欠落セグメントを評価することでデータベース メタを取得できます。次に、「所有者に通知する」、「ファイル メタを削除する」、またはこの両方のアクションを実行できます。
私は、実際の大きなファイルを DBMS 自体にバイナリ コンテンツとして格納するという考えには反対です。
DBMS はデータと分析に関するものであり、FileSystem ではありません。私の謙虚な意見が重要である場合は、決してそのように使用しないでください。