隨筆 - 5  文章 - 2  trackbacks - 0
          <2006年11月>
          2930311234
          567891011
          12131415161718
          19202122232425
          262728293012
          3456789

          常用鏈接

          留言簿(1)

          隨筆分類

          隨筆檔案

          搜索

          •  

          最新評論

          閱讀排行榜

          評論排行榜

          MySQLにファイルを格納する
          MySQLは多くのフィールド(データ)型をサポートしており、文字や數(shù)値、日付や時間のほか、バイナリデータまで格納できます。バイナリデータを格納するのは、「BLOB(ブロブ)型」。今回は、このBLOB型を使って、デジカメ寫真を格納する方法を紹介します。
          JAVA Developer 2003年11月號より転載

          MySQLのBLOB型は4つ
           MySQLは、TINYBLOB、BLOB、MEDIUMBLOB、LONGBLOBという4種類の可変長バイナリデータを格納する型をサポートしています(表1)。それぞれの違いは、格納できるデータの最大長です。今回の目的はデジカメ寫真ですので、1M~2MB前後のデータを格納できるMEDIUMBLOB型を使います。

          最大サイズ(バイト)
          TINYBLOB255(28-1)
          BLOB65,535(216-1)
          MEDIUMBLOB16,777,215(224-1)
          LONGBLOB4,294,967,295(232-1)

          アップロードはJakartaCommons FileUploadを利用
           まずはクライアントPCからサーバーへのファイルアップロード機能を?qū)g裝していきます。
           はじめは、ファイルアップロード用のフォームです。ここでのポイントは、methodに必ず「post」を指定し、「enctype="multipart/form-data"」を記述することです。また、アップロードするファイル名は、「<input type="file" name="file1">」のように、typeで「file」を指定します。

          リスト1 アップロードフォーム(抜粋)

          <form name="upload" method="post"
          ? ? ?enctype="multipart/form-data">
          ファイル1:<input type="file" name="file1"><br>
          ファイル2:<input type="file" name="file2"><br>
          ファイル3:<input type="file" name="file3"><br>
          <input type="submit" value="アップロード">
          <input type="reset" value="リセット"><br>
          </form>

           このフォームからデータを受け取って処理する部分には、JakartaCommons FileUpload 1.0(commons-fileupload-1.0.jar)を利用します。FileUploadのDiskFileUploadクラスでは、アップロードできる最大サイズ、メモリー內(nèi)に保持するサイズなどを指定したあと、requestオブジェクトをパースし、ListにアップロードするFileItemオブジェクトを格納します(リスト2-(1))。Iteratorを使ってFileItemオブジェクトを取り出し、ImageFileオブジェクトを生成して、アップロードデータを格納していきます(リスト3)。

          リスト2 ファイルのアップロードを?qū)g裝(抜粋)

          DiskFileUpload uploader =
          ? ?new DiskFileUpload();
          uploader.setSizeMax(UPLOAD_LIMIT_SIZE);
          uploader.setSizeThreshold(IN_MEMORY_SIZE);

          List items =
          ? ?uploader.parseRequest(request); //-(1)
          Iterator iter = items.iterator();
          while (iter.hasNext()) {
          ? ?ImageFile image = new ImageFile();
          ? ?if (image.set((FileItem)iter.next())) {
          ? ? ? ?iData.add(image);
          ? ?}
          }

          リスト3 ImageFileクラス

          public class ImageFile {
          ? ?public String fileName;
          ? ?public String contentType;
          ? ?public int fileSize;
          ? ?public InputStream inputStream;

          ? ?public boolean set(FileItem item)
          ? ? ? ? ? ?throws IOException {
          ? ? ? ?fileSize = (int)item.getSize();
          ? ? ? ?if (fileSize > 0) {
          ? ? ? ? ? ?fileName = item.getName();
          ? ? ? ? ? ?contentType = ? ? ?
          ? ? ? ? ? ? ? ?item.getContentType();
          ? ? ? ? ? ?inputStream =
          ? ? ? ? ? ? ? ?item.getInputStream();
          ? ? ? ? ? ?return (fileName != null &&
          ? ? ? ? ? ? ? ? ? ?contentType != null);
          ? ? ? ?}
          ? ? ? ?return false;
          ? ?}
          }

           次に、ImageFileオブジェクトのデータをデータベースへ登録します。ここでは、BLOB型へのデータ登録にPreparedStatementを使います(リスト4-(2))。PreparedStatementには、データ型別にsetXXXメソッドが用意されており、その中にBLOB型に対応するsetBinaryStreamメソッドがあります(リスト4-(3))。このほかBLOB型に対応するメソッドとしては、setBlobやsetBytesメソッドがあります。

          リスト4 PreparedStatementを使って登録(抜粋)

          Connection con = ds.getConnection();
          PreparedStatement stmt = ?
          ? ?con.prepareStatement(
          ? ?"INSERT INTO "+
          ? ?"image(name,type,size,rawdata,entry) "+
          ? ?"VALUES(?, ?, ?, ?, ?)"); //-(2)

          stmt.setString(1, image.fileName);
          stmt.setString(2, image.contentType);
          stmt.setInt(3, image.size);
          stmt.setBinaryStream(4,
          ? ?image.inputStream, image.size); //-(3)
          java.util.Date now = new java.util.Date();
          stmt.setTimestamp(5,
          ? ?new Timestamp(now.getTime()));

          stmt.executeUpdate();

          stmt.close();
          con.close();


          ※imageはImageFileクラスのオブジェクト

           ここまでで、アップロードからデータベースへ登録するまでのコーディングは終了です。テスト用にいくつかファイルをアップロードし、データベースに登録されていることを確認します。

          「PacketTooBigException」で
          ファイルが格納できない

          図1
          図1 例外発生!

           さらにファイルをアップロードしていくと、比較的大きめのファイルの場合に例外が発生して、うまく格納できないという癥狀に遭遇しました(図1)。例外はJDBCが投げているものです。例外名を手がかりにFAQを探してみると、それらしき記述を発見。解決策は、my.iniの[mysqld]セクションに、次のオプションを記述するというものです。


          max_allowed_packet=4M

           このオプションは、パケットの最大サイズを指定するものです。上記の場合はパケットサイズを4MBに指定しています。4MBは、普段使っているデジカメのファイルサイズより多少余裕を持たせた値です。あまり大きすぎても無駄にメモリーを使うだけですから、登録したいファイルサイズを考慮した値を指定しましょう。
           MySQLを再起動し、先ほどうまく格納できなかったファイルを再度アップロード。今度は問題なく格納できました。これで、ファイルのアップロードからデータベースへの格納までは大丈夫。アップロードしたイメージの表示や検索などの機能は、これからじっくり盛り込んでいこうと思います。
           読者の皆さんも、BLOB型を活用してみませんか。

          參考リンク
          FileUpload 1.0
          Jakarta CommonsなどのAPI翻訳

          関連リンク
          ▼JAVA Developer
          ▼定期購読のご案內(nèi)
          ▼バックナンバー販売協(xié)力店

          posted on 2006-11-14 10:03 PrettyBoy 閱讀(625) 評論(0)  編輯  收藏

          只有注冊用戶登錄后才能發(fā)表評論。


          網(wǎng)站導(dǎo)航:
           
          主站蜘蛛池模板: 孟连| 金山区| 垣曲县| 汤阴县| 聂荣县| 社会| 诸暨市| 惠东县| 疏勒县| 哈尔滨市| 石门县| 日土县| 宝坻区| 焉耆| 封开县| 自贡市| 汝城县| 响水县| 繁峙县| 色达县| 星子县| 乾安县| 周至县| 响水县| 石首市| 海兴县| 中牟县| 泸西县| 灵寿县| 商水县| 合山市| 酒泉市| 长治市| 盖州市| 定远县| 玉环县| SHOW| 台北县| 彰武县| 泽普县| 亚东县|