Webアプリケーションに、ユーザーがプロフィール写真をアップロードできるフォームがあるとします。
ファイルサイズ、サイズなどに関する要件はほとんどありませんが、ユーザーが画像をアップロードするとき、システムでどのように名前を付ける必要がありますか?一貫性があり、かつユニークである必要があると思います。
多分GUIDですか?
a5c627bedc3c44b7ae7c06a44fb3fcf8.jpg
タイムスタンプ?
129899740140465735.jpg
ハッシュ?例:md5
b1a9acaf295cf14ffbc5b6538294562c.jpg
これを行うための標準的または推奨される方法はありますか?
一意性と有用性という2つの目標を達成する必要があります。
GUIDを使用すると一意性が保証されますが、ある日、ファイルが元のソースから切り離されて、問題が発生する可能性があります。
私の典型的な解決策は、userID(ユーザーに属している場合)またはアップロードされた日時(これが重要な場合)、またはアップロード時に使用されるファイル名などの重要な情報をファイル名に埋め込むことです。
これにより、ファイル名に埋め込まれた情報を使用して、たとえば、バグからの回復やレコードの誤った削除などにより、実際にあなたの肌を救うことができます。あなたが持っているすべてがGUIDであり、あなたがカタログを失った場合、あなたはそれをきれいにする仕事の一体を持っています。
たとえば、「My Holiday:Florida 23.jpg」というファイルがuserID 98765によって2013/04/04の12:51:23にアップロードされた場合、ランダムな文字列ad8a7dsf9
を追加して、次のような名前を付けます。
20130404125123-ad8a7dsf9-98765-my-holiday-florida-23.jpg
アプリケーション(エクスプローラーなど)にストレスを加えて、ディレクトリを開いたときにクラッシュしないようにする必要があります。実際のファイルシステムにストレスをかけることはまずありませんが、何千ものファイルを保存する場合は、この点を考慮する必要があります。
あなたが何千ものファイルを保存することを期待しているなら、私の提案はフォルダに分割することです。例えば upload\silo001
、upload\silo002
など。ファイルのバランスを取るか、フォルダが特定の数のファイルに到達するまで待ってから、別のファイルを作成できます。
命名に関しては、常にGUIDでファイルに名前を付けます。これはグローバルに一意であるためです。アップロードから拡張子をプルし、一致するようにファイルの拡張子を設定しますが、実際の名前は新しいGuidから設定されます。
これをRDBMSと組み合わせて実行していて、複数のカテゴリ(つまり、製品、カテゴリなど)がある場合は、upload\products
、upload\categories
など、行IDをファイル名として使用できます。
ベストプラクティスに関しては、私も過去を調べて何も見つかりませんでした。私は私の開発者の何人かと話し合っている間に上記を思いつきました。
私が何年も前に取り組んだソリューションの1つで、これを行いました。ユーザーIDの一部のサブフォルダーなので、ユーザーIDが232950192の場合
サブフォルダimages/23/29/50/192/232950192があります
最後のフォルダーには、albunsやprofile imgsなどのフォルダーがあります。
しかし、データベースにもすべてを保存し、ファイルシステムに保存して、Webサーバーにすばやくアクセスできるようにします(これにはキャッシュも含まれます)。
とにかく、最終的な画像は元の画像名になります。バージョンを保持する必要はありませんでした。しかし、最終的なアルバム名の下に、またはバージョンIDを持つデータベースに、より多くのサブフォルダーを保持できるものについては。本番環境に移行すると、現在の構造で時間のかかるエラーが発生しやすい修正を行わないと、物事を変更することが困難になるため、それを考える必要があります。
Javaにサブフォルダを作成し、その中にファイルを作成するのは非常に簡単です:
File folder = new File(pathwithslashes);// like "images/23/29/50/192/232950192"
folder.mkdirs();
File imgFile = new File(folder, name);
//Now get output stream etc
サブフォルダーの日付スタンプを取得するには:SimpleDateFormat sdf = new SimpleDateFormat( "/ yyyy/MM/dd /"); pathwithslashes = pathwithslashes + sdf.format(now); // now is util.Date File folder = new File(pathwithslashes);
ドットネット https://stackoverflow.com/questions/5482230/c-sharp-equivalent-of-javas-mkdirs
Md5または概念的に同等のものだけを使用することをお勧めします。コンテンツのダイジェストによってファイルの名前を変更することにより、一意性を付与するだけでなく(常に可能な限り画像をキャッシュし、コンテンツベースの名前変更を使用すれば、適切な名前を使用して、画像を実質的に永久にキャッシュできます)。
また、大したことではありませんが、別のユーザーがまったく同じ画像をアップロードするというのは、純粋な仮説的なケースではありません。箱から出してすぐに、小さなデータストレージ最適化があります。
他に提案されているものについては、私と同様、私はanyの種類の補助情報をファイル名に保持することに強い反対者です。私はかなり若かった(そして少しスリムでした:)とき、私はPerl開発者であり、Perl文字列パターン機能は素晴らしいので、常識的に許される限り多くの補助情報をファイル名に格納する疑わしい習慣がありました。そして、私は、Web開発について言えば、ファイル名とは別にファイルに関連付けられたデータを保持するほうが常に良い選択であるという結論に達しました。
モバイルインターフェースが支配的になっている今日、実際のファイル名は5、10年前ほど重要ではなくなったことに留意してください。ただし、これがアプリケーションのコンテキストで重要になる場合でも、Content-Disposition: attachment; filename="pretty_file_name.jpg"
HTTPヘッダーを使用して古い学校の魔法を常に使用し、必要な関連ファイル名を作成できます。また、最近のブラウザは新しいHTML5属性 download への道を開いています。 「人間が読める」画像名を実際に確認することは、ほとんどの場合に考慮すべきことだとは思いません。
UPD:1つのディレクトリにファイルが多くなりすぎないように変更できます。最初の3文字を取り、dirを作成します。