web-dev-qa-db-ja.com

PHP MySQLに画像を保存するかどうか?

PHPにユーザーが最初にログインする必要がある場所に小さなWebアプリケーションを作成しました。ユーザーがログインしたら、「プロファイル」の一部として小さなサムネイルを表示するつもりです。

スペースを節約するために画像が特定のサイズを下回っていることを確認するか、特定の解像度またはその両方であることを確認する必要があります。
そのための最善の方法がまだわからない、どんなアイデアも歓迎します。

また、イメージをMySQLのusersテーブルにblobとして保存するか、一意のIDを持つ別のimagesテーブルに保存する方がよいかどうかを検討しています。適切な画像IDをusersテーブルに保存するか、アップロードしたファイルを(アップロードページを介して)サーバーに保存し、theUsersUniqueUsername.jpgとして保存します。最適なオプションは?

私はここにmysqlへの画像の保存に関するチュートリアルを見つけました: http://www.phpriot.com/articles/images-in-mysql

私はただの趣味のプログラマーであり、これまでにこのようなことをしたことがないので、例や詳細の多くが高く評価されています。

31
occhiso

常にコンテキストに依存しますが、通常、ユーザーイメージをファイルシステムの/content/user/{user_id}.jpgというフォルダーに保存し、データベースをできるだけ煩わしくしないようにします。

40
Mario

画像をファイルとして保存し、ファイルURIをデータベースに保存することをお勧めします。すべての画像をデータベースに保存すると、後のスケーリングで問題が発生する可能性があります。

チェックアウト この答え も:

SQL Serverに対するMicrosoftの助言は、速度とサイズのために、データベース内のリンクを使用して画像をファイルシステムに格納することでした。彼らは好みを少し和らげたと思いますが、データベースのスペースを取らないので、サイズに関しては確かにそれをより良い考えと考えます。

23
Philip Morton

BLOBを使用したオーバーヘッドは、特に正しく設定した場合、ほとんどの人が信じているよりもはるかに少なくなります。バイナリファイルを格納するためにDBを実行するだけの別のサーバーを使用する場合、実際にはファイルシステムをまったく使用せず、ファイルシステムからのオーバーヘッドを回避できます。

それはあなたがあなた自身にいくつかのサーバーを持っていない限り、最も簡単/最良の方法はそれらをファイルシステムに保存することだと言いました

  • ファイルの絶対URLをDBに保存せず、一意の部分(場合によっては1つまたは2つのフォルダー)のみを保存してください。 2009/uniqueImageName.jpgまたは単にuniqueImageName.jpg。次に、ページでホストと他のフォルダを前面に追加するだけで、画像を移動する際にある程度の柔軟性が得られます。変更する必要があるのは、PHP/ASP.NETページの1行または2行です。

  • セキュリティのためにドキュメントルートの外側に保存する必要はありません-DENY FROM ALLを含む.htaccessファイルは同じように機能し、柔軟性が向上します

  • セキュリティのために画像をそれほど「シャント」する必要はありません。getImage.phpページなどを用意し、実際のURLをsrcimageに挿入する代わりに、 getImage.php?file=uniqueImageName.jpgのようなもの。次に、getImage.phpファイルは、ユーザーが承認されているかどうかを確認し、画像を取得するかどうかを確認できます。

  • 保存時に一意であることが保証されている名前(できれば整数、つまり主キー)を使用します。一部のファイルシステム(Windowsなど)では大文字と小文字が区別されないため、JoeBloggs.jpgおよびjoebloggs.jpgはデータベースに対して一意です、ただしファイルシステム用ではないため、1つが別のファイルシステムを上書きします。

  • 画像には別のテーブルを使用し、画像の主キーをユーザーテーブルに保存します。さらにフィールドを追加したり、将来変更を加えたりしたい場合は、より簡単になります。これも良い方法です。

SEOなどが心配な場合は、アップロード時に画像の元のファイル名を別のフィールドに保存して、出力(altタグなど)で使用できます。

17
Joseph Earl

常識に挑戦!

もちろんコンテキストに依存しますが、MySQLデータベースにBLOBSとして保存された何千もの画像とドキュメント(平均サイズ= 2MB)を備えた非常に大規模なアプリケーションがあり、アプリケーションは256MBのメモリを搭載したサーバーで正常に動作します。秘密は正しいデータベース構造です。常に2つの個別のテーブルを保持します。1つにはファイルに関する基本情報を格納し、もう1つのテーブルにはBLOBとそれにアクセスするための主キーのみを含める必要があります。すべての基本的なクエリは詳細テーブルに対して実行され、他のテーブルはファイルが実際に必要な場合にのみアクセスされ、インデックス付きキーを使用してアクセスされるため、パフォーマンスは非常に良好です。

データベースにファイルを保存することの利点は複数あります。

  1. ファイルシステムをバックアップする必要がないため、はるかに簡単なバックアップシステムが必要です。
  2. バイナリをリリースする前に検証できるため、ファイルセキュリティの制御がはるかに簡単です(そうです、ファイルを非パブリックディレクトリに保存し、スクリプトにファイルを読み取らせて逆流させることができますが、パフォーマンスは著しく速くなりません。
  3. (#1と同様)「ユーザーコンテンツ」と「システムコンテンツ」を明確に分離し、移行とクローン作成を容易にします。
  4. バージョン管理を追加するために必要なスクリプトの変更が少ないため、ファイルの管理、バージョンの変更の追跡/保存などが簡単になります。

パフォーマンスが大きな問題であり、セキュリティとバックアップがそうでない場合(または、優れたfsバックアップシステムがある場合)、それをFSに保存できますが、それでも、ファイル(イメージの場合)をDBに保存することがよくありますそして、最初に使用された後、画像をキャッシュフォルダーに書き込むキャッシュスクリプトを作成します(これにより、より多くのHD領域が使用されますが、これが制限要因になることはほとんどありません)。

とにかく、明らかにFSは多くの場合うまく機能しますが、個人的にはDB管理がはるかに簡単で柔軟性が高いと思います。うまく書けば、パフォーマンスのペナルティは非常に小さくなります。

16
Ben D

画像をDBに保存するショップを作成しました。これは開発中にうまく機能しましたが、実稼働サーバーでテストすると、ページの読み込み時間が長すぎ、DBサーバーに不要な負荷がかかりました。

バイナリファイルをDBに格納することは魅力的であるように見えますが、それらをフェッチして操作すると、ファイルシステムにファイルを保存し、パス/メタデータをDBに格納するだけで回避できる複雑さが増します。

これは、永遠の議論の1つであり、双方に優れた議論がありますが、私のお金のために、画像をDBから遠ざけます。

10
Neil Aitken

私は最近このヒントのリストを見ました: http://www.ajaxline.com/32-tips-to-speed-up-your-mysql-queries

ヒント17:Webアプリケーションの場合、画像やその他のバイナリアセットは通常ファイルとして保存する必要があります。つまり、ファイル自体ではなく、ファイルへの参照のみをデータベースに格納します。

したがって、画像へのファイルパスを保存するだけです:)

9
AntonioCS

以前のプロジェクトで両方のソリューション(ファイルシステムとデータベース永続イメージ)を実装しました。私の意見では、データベースに画像を保存する必要があります。理由は次のとおりです。

  1. アプリサーバーがクラスター化されている場合、ファイルシステムストレージはより複雑になります。共有ストレージが必要です。現在の環境がクラスター化されていなくても、必要なときにスケールアップすることがより困難になります。
  2. とにかく静的コンテンツにCDNを使用し、アプリをOriginとして設定する必要があります。つまり、アプリは特定の画像に対して1回だけヒットされ、その後CDNにキャッシュされます。 CloudFrontは非常に安価でセットアップが簡単です...それを使用しない理由はありません。動的コンテンツの帯域幅を節約します。
  3. データベースに永続化されたイメージを開発する方がはるかに高速です(したがって、安価です)
  4. データベースの永続化されたイメージで参照整合性を取得します。ファイルシステムに画像を保存している場合は、一致するデータベースレコードのない孤立ファイルが必ず存在するか、ファイルリンクが壊れたデータベースレコードが存在します。これは起こります...それは時間の問題です。これらをクリーンアップするために何かを書く必要があります。

とにかく、私の2セント。

6
Dustin
  1. とにかく、ファイルを格納するためのものではない場合のblobデータ型は何ですか?
  2. アプリケーションがファイルにアクセスする前に承認を必要とする場合、変更は次のとおりです。a)DOCUMENT_ROOTの外部にファイルを保存します(直接アクセスできないため、b)アプリケーションからファイルのコンテンツ全体を送信します。 (もちろん、たぶんあなたはある種の一時的な移動、ハッシュへの移動、しかし公的にアクセス可能なファイル名のことをしているでしょう)。とにかく、メモリのオーバーヘッドがあり、データベースからデータを取得することもできます。
  3. ファイルをファイルシステムに保存する必要がある場合は、上記のAndreasの提案に従い、すでに知っているもの(つまり、関連するテーブルの主キー)を使用して名前を付けます。
4
Sam Wilson

ほとんどのデータベースエンジンは非常に高度であり、BLOBのデータを格納しても不都合はありません(肥大化したデータベースなど)。 1つの利点は、画像が既にデータベースにあるときに、リンク切れが発生しないことです。そうは言っても、私は常に自分でファイルをディスクに格納し、データベースにURIを与えるようにしています。使い方次第です。ページが非常に動的で頻繁に変更される場合(名前空間がない場合)は、img-in-dbを処理する方が簡単な場合があります。それはあなたが好むものに終わると私は言わなければなりません。

2
Jens Jansson

画像をデータベースに保存しないことをお勧めします。代わりに、すべてのユーザーがdbで自分のプロファイルに関連付けられた一意のIDを持つため、そのIDを使用してサーバーに物理的にイメージを保存します。

例えばユーザーのIDが23の場合、www.yourname.com/users/profile_images/23.jpgに画像を保存できます。次に、表示するには、画像が存在するかどうかを確認し、それに従って表示するか、汎用アイコンを表示します。

2
Alec Smart

他の人が示唆したように:

  • 画像をファイルシステムに保存する
  • ファイル名を保存せずに、ユーザーID(または「知っている」もの)を使用してください。
  • 静的データを別のサーバーに配置します(通常のサーバーのエイリアスとして "static.yourdomain.com"を使用している場合でも)

どうして ?

データベースが大きくなると、取得速度が遅くなります。画像をデータベースに保存すると、データベースのサイズが大きくなります。ファイル名を保存すると、データベースのサイズが大きくなります。

静的データを別のサーバーに配置する(エイリアス):

  • 簡単にスケールアップできます
  • ほとんどのブラウザは同じサーバーに3つ以上のリクエストを送信しません。静的データを「2番目の」サーバーに配置することで、ロードを高速化します。
2
Andreas

何日か研究した後、データベースに画像とバイナリを保存するシステムを作りました。

それは素晴らしかった。アクセス制御、画像のサイズ変更(もちろん、画像を動的に拡大縮小することはしません)、統計、バックアップ、メンテナンスなど、ファイルを100%制御しています。

私の速度テストでは、システムの速度が10倍遅くなりました。ただし、まだ本番環境にはないため、システムキャッシュやその他の最適化を実装します。

MVCを使用して、共有ホスト上でまだ開発中のこの実際の例を確認してください: http://www.gt8.com.br/salaodocalcado/calcados/meia-pata/

この例では、ユーザーがログインすると、さまざまな画像が表示されます。すべての製品のイメージとその他のバイナリはDBにあり、キャッシュされておらず、FSにはありません。

専用サーバーでいくつかのテストを行ったところ、結果は期待をはるかに超えていました。

だから、私の個人的な意見では、それを達成するには大きな努力が必要ですが、画像をDBに保存することには価値があり、その利点は短所よりはるかに価値があります。

1
user2377782

私の場合、ファイルをファイルシステムに保存します。私の画像フォルダーで、アイテムID(dbからの行)に基づいて名前が付けられた各アイテムの新しいフォルダーを作成します。そして、0から始まる順序で画像に名前を付けます。つまり、次のようなItemsという名前のテーブルがあるとします。

       Items      
|-----|------|-----|
| ID  | Name | Date|
|-----|------|-----|
| 29  | Test1| 2014|
|-----|------|-----|
| 30  | Test2| 2015|
|-----|------|-----|
| 31  | Test3| 2016|
|-----|------|-----|

私の画像ディレクトリは次のようなものです:

images/
      29/
      30/
      31/


images/29/0.png
images/29/1.jpeg
images/29/2.gif

等.

0
Elnoor

他の誰もがあなたに言ったように、決して画像をデータベースに保存しないでください。ファイルシステムはファイルの保存に使用されます->画像はファイルです->ファイルシステムに保存します:-)

0
Lucacri

これらは両方のソリューションの長所です

BLOBSで:

1)長所:サーバー間のファイル同期のようなトリッキーなポイントを処理する必要がないため、クラスターを管理する容易さ

2)DBバックアップも完全になります

ファイル内

1)ネイティブキャッシングは手軽です(これは、DBで再設計する必要のない更新とヘッダーを備えた、以前のコメントの欠落点です(DBはデフォルトで最終変更時間を処理していません)

2)後で簡単にサイズ変更できる

3)モデレートの容易さ(フォルダーを調べて、すべてが正しいかどうかを確認する)

これらすべての理由と、データベースの2つの長所がファイルシステムでの複製が容易であるため、ファイルを強くお勧めします。

0
Irem

私のimgをblobとしてテストしたところです。このソリューションは、サーバー上のファイルとしての画像よりも動作が遅くなります。読み込み時間は、DBまたはhttpの画像と同じである必要がありますが、異なります。どうして?確かに、画像がサーバー上のファイルである場合、ブラウザーはそれをキャッシュして最初に1回だけロードできます。画像がDBから送信されると、毎回再度読み込まれます。それが私の意見です。ブラウザのキャッシュについては間違いかもしれませんが、動作が遅くなります(ブロブ)。 Sry私の英語、何でも; P

0
Dudeist