如何实现图片的上传以及将图片保存到Mysql

如何实现图片的上传以及将图片保存到Mysql
MySQLにファイルを格納する
MySQLは多くのフィールド(データ)型をサポートしており、文字や数値、日付や時間のほか、バイナリデータまで格納できます。バイナリデータを格納するのは、「BLOB(ブロブ)型」。今回は、このBLOB型を使って、デジカメ写真を格納する方法を紹介します。
JAVA Developer 2003年11月号より転載

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

最大サイズ(バイト)
TINYBLOB 255(28-1)
BLOB 65,535(216-1)
MEDIUMBLOB 16,777,215(224-1)
LONGBLOB 4,294,967,295(232-1)

アップロードはJakartaCommons FileUploadを利用
 まずはクライアントPCからサーバーへのファイルアップロード機能を実装していきます。
 はじめは、ファイルアップロード用のフォームです。ここでのポイントは、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クラスでは、アップロードできる最大サイズ、メモリー内に保持するサイズなどを指定したあと、requestオブジェクトをパースし、ListにアップロードするFileItemオブジェクトを格納します(リスト2-(1))。Iteratorを使ってFileItemオブジェクトを取り出し、ImageFileオブジェクトを生成して、アップロードデータを格納していきます(リスト3)。

リスト2 ファイルのアップロードを実装(抜粋)

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
▼定期購読のご案内
▼バックナンバー販売協力店

你可能感兴趣的:(如何实现图片的上传以及将图片保存到Mysql)