アップロードされた画像に名前を付けるためのベストプラクティスは何ですか?


15

ユーザーがプロフィール写真をアップロードできるフォームがWebアプリケーションにあるとします。

ファイルサイズ、サイズなどに関する要件はほとんどありませんが、ユーザーが画像をアップロードするときに、システム上でどのように名前を付ける必要がありますか?一貫性があり、一意である必要があると思います。

多分GUID?

a5c627bedc3c44b7ae7c06a44fb3fcf8.jpg

タイムスタンプ?

129899740140465735.jpg

ハッシュ?例:md5

b1a9acaf295cf14ffbc5b6538294562c.jpg

これを行うための標準的な方法または推奨される方法はありますか?


7
ユーザーごとに1つのプロファイル画像のみを保存することが目標の場合、ユーザーIDと同じ名前をファイルに付けることが明白な選択だと言う人もいます。
アランバーバー

DateTime.Nowは15ミリ秒ごとに更新されるため、タイムスタンプはお勧めできません。たとえば、バルクロード、キューに入れられたリクエストなどの間に衝突の可能性が高くなります
。– jhexp

回答:


27

一意性と有用性という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

  • 一意性は、日付と時刻、およびランダム文字列(/ dev / urandomまたはCryptGenRandomから適切にランダムである場合)によって保証されます。
  • ファイルが切り離された場合、ユーザー、日付と時刻、およびタイトルを識別できます。
  • すべてが小文字に折り畳まれ、英数字以外のものはすべて削除され、ダッシュで置き換えられます。これにより、単純なツールを使用してファイル名を簡単に処理できます(たとえば、誤って記述されたスクリプトを混乱させるスペース、コロンやその他のファイルシステムで禁止されている文字はありません、 等々)。

7
ハウスキーピングのために、ユーザーIDごとに個別のディレクトリを作成することをお勧めします。そうすることで、ユーザーを削除した場合、すべての写真を探し回る必要がなくなります。-そう98765/20130404125123-ad8a7dsf9-my-holiday-florida-23.jpg
Shadur

1
ランダム文字列によって理論的に一意性は提供されません。
Kolyunya

4
@Kolyuny、それは本当です、保証されたグローバルな一意性はGUIDでさえ現実にあるプロパティではないという意味で(重複したMACアドレスの発行によりv1のGUIDでさえ破壊されます)。あなたが得ることができるのは、一意性の統計的尤度だけです。ただし、ファイルが既に存在するかどうかを確認して(アトミックにCreateFilewith を使用CREATE_NEW)、存在する場合は異なるランダム性を使用して、一意性を確保できます。
ベン

「すべての英数字以外はダッシュで取り外して交換した場合、何を下げるために折り畳まれ、」私はすべての非英数字を削除し、最後のダッシュを除くスコアの下に置き換え、それ混在ケース続けるだろう
tgkprog

4

アプリケーション(エクスプローラーなど)に負荷をかけ、ディレクトリを開いたときにクラッシュさせたくない場合。実際のファイルシステムにストレスをかけることはまずありませんが、数千のファイルを保存する場合は、これを考慮する必要があります。

何千ものファイルを保存することを期待している場合、私の提案はフォルダに分割することです。たとえばupload\silo001upload\silo002などあなたはどちらかあなたのファイルのバランスをとるか、フォルダ、ファイルの一定数に達するまで待機し、その後、別のものを作成することができます。

命名に関しては、グローバルに一意であるため、常にGUIDを使用してファイルに名前を付けます。アップロードから拡張子を取得し、ファイルの拡張子を一致するように設定しますが、実際の名前は新しいGUIDから設定されます。

あなたはRDBMSと一緒にこれを行うと、いくつかのカテゴリ、すなわち製品、カテゴリ、などを持っているなら、あなたは持っている可能性がありupload\productsupload\categoriesなど、あなたがファイル名として行IDを使用することができます。

ベストプラクティスの観点から、私も過去を見て、何も見つかりませんでした。私は開発者の何人かと議論しながら上記を思いつきました。


2

私が何年も前に取り組んだソリューションの1つで、これを行いました。ユーザーIDの一部のサブフォルダーです。ユーザーIDが232950192の場合

サブフォルダimages / 23/29/50/192/232950192があります

最後のフォルダには、albunsやプロファイルimgなどのフォルダがあります

ただし、データベースにもすべてを保存し、ファイルシステムに保存して、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);

ドットネット/programming/5482230/c-sharp-equivalent-of-javas-mkdirs


ネストされたディレクトリを提案するための+1。私は、このフォルダは「あまりにも多くの」ファイルが含まれている場合、パフォーマンスの問題が発生することができます別のファイルシステムとして検討することが重要だと思う:stackoverflow.com/questions/197162/...support.microsoft.com/kb/130694/en-usなどを、
deizel

1
はい、別のシステムでは、400,000個を超えるファイルがあるdirでrmdirしようとしたときに、Webサーバーがハングしました。このようなフォルダがさらにありました。そのため、dir / pというカスタムプログラムを使用して、一度に削除するファイルをいくつか取得しました。数時間かかりましたが、ダウンタイムはありませんでした:)
tgkprog

1

md5または概念的に同等のものを使用することをお勧めします。コンテンツのダイジェストによってファイルの名前を変更することにより、一意性を付与するだけでなく(常に画像を可能な限りキャッシュし、コンテンツベースの名前を変更することで、適切なファイル名で、画像を実質的に永久にキャッシュできます)。

また、大したことではありませんが、それでも、異なるユーザーがまったく同じ画像をアップロードするというのは純粋な仮説的なケースではありません。箱から出してすぐに、少量のデータストレージを最適化できます。

提案された他のことに関しては、私に関しては、ファイル名にあらゆる種類の補助情報を保持することに強い反対者です。私がはるかに若かったとき(そして少しスリム:)、私はPerl開発者であり、Perlの文字列パターン機能が素晴らしいので、常識的に許される限り多くの補助情報をファイル名に格納するという疑わしい習慣がありました。そして、Web開発については、ファイルに関連付けられたデータをファイル名とは別に保持する方が常に良い選択であるという結論に達しました。

現在、モバイルインターフェイスが支配的になっているとき、実際のファイル名は5、10年前ほど重要ではないことに注意してください。ただし、これがアプリケーションのコンテキストで重要になる場合でも、Content-Disposition: attachment; filename="pretty_file_name.jpg"いつでもHTTPヘッダーを使用して、昔ながらの魔法を使用して、必要な関連ファイル名を作成できます。また、最新のブラウザーは、新しいHTML5属性であるdownloadへの道を開いています。「人間が読める」画像名を実際に表示することは、ほとんどの場合に考慮する必要があるとは思いません。

UPD:1つのディレクトリに多くのファイルが含まれないように変更できます。最初の3文字を取得してディレクトリを作成します。


1
md5は本当にユニークですか?
I.devries

@ I.devries、私は専門家ではありませんが、私が知る限り、この目的には十分です。-良いハッシュアルゴリズムは、実際に同じサイズの実体が少なく、おそらく衝突持っていることを認めるので、あなたは、さらに、ファイルのサイズを確認します場合は特にstackoverflow.com/questions/2442632/...
shabunc

-1

sha4のようなものと衝突する可能性はわずかです。ハッシュをユーザーIDまたは単純な日付と組み合わせると、さらに少なくなります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.