コンピュータクワガタ

かっぱのかっぱによるコンピュータ関連のサイトです

ドラッグ&ドロップによるファイルのアップロード

Tomcat 7.0の最新安定版もリリースされたことですので、標準でサポートされたファイルアップロードを試してみました。

Servlet 3.0 File Upload 機能 - 寺田 佳央 - Yoshio Terada

http://yoshio3.com/2010/03/11/servlet-3-0-file-upload-%E6%A9%9F%E8%83%BD/

にそのものがのっていましたので、これを元に試してみようと思いましたが、そのものすぎるのでやめました。
一応やりましたが、ここでは書きません。

代わりに、ドラッグ&ドロップしたファイルのアップロードを行うServletを書いてみました。このServlet自体はServlet 3.0である必要性はありません。具体的なコードは以下になります。まず、動作のもととなるHTMLファイルです。

<!DOCTYPE html>
<html>
 <head>
  <meta charset="utf-8">
  <title>ファイルのアップロード</title>
  <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.js"></script>
  <script type="text/javascript">
var result;

$(function() {
    window.addEventListener('dragover', function(event) {
        event.preventDefault();
    }, false);

    document.getElementById('dragArea').addEventListener('drop', function(event) {
        event.preventDefault();
        var dt = event.dataTransfer;
        result = $('#result');
        result.html('');
        for (var i = 0; i < dt.files.length; i++) {
            upload(dt.files[i], new FileReader());
        }
    }, false);

    function upload(file, reader) {
        var name = file.name;
        reader.onload = function() {
            jQuery.post('/Upload/FileUploadServlet',
                { name: name, content: reader.result },
                function() {
                    result.append(name + 'をアップロードしました。<br>');
                },
                'json'
            );
        };
        reader.readAsDataURL(file);
    }
});
  </script>
  <style type="text/css">
#dragArea {
  border: solid 1px #000000;
  background-color: #cccccc;
  width: 100px;
  height: 100px;
}
  </style>
 </head>
 <body>
  <div id="dragArea">ファイルをここにドラッグ</div>
  <form id="result"></form>
 </body>
</html>

ファイルは、FileReader#readAsDataURLメソッドを用いて、Base64エンコードしてアップロードします。
処理は、1ファイルずつAjaxで行っています。jQuery.postメソッドを用いて、FileUploadServletに対してPOSTリクエストを投げています。
その、FIleUploadServletの内容は以下です。

package sample;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.codec.binary.Base64;

@WebServlet("/FileUploadServlet")
public class FileUploadServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;

    private static final String BASE64 = "base64,";
    
    protected void processRequest(HttpServletRequest request, HttpServletResponse response)
    throws ServletException, IOException {
        request.setCharacterEncoding("utf-8");
        String name = request.getParameter("name");
        String content = request.getParameter("content");
        if (content.length() == 0) {
            return;
        }
        byte[] data = Base64.decodeBase64(content.substring(content.indexOf(BASE64) + BASE64.length()));
        
        File file = new File("d:\\temp", name);
        OutputStream fos = new FileOutputStream(file);
        fos.write(data);
        fos.flush();
        fos.close();
        
        return;
    }

    @Override
    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws IOException, ServletException {
        processRequest(request, response);
    }
}

実行結果は以下のようになります。

ドラッグ&ドロップしたファイルは、d:\temp以下に置かれます。

ソースの内容を確認するとSerlvet 3.0なのは、@WebServletアノテーションの部分です。このアノテーションによりServletとURLのマッピングを行っています。
この例で言えば、/コンテキストパス/FileUploadServletにアクセスするとこのServletが呼ばれる事になります。
今回、web.xmlは一切書いていません。非常に簡単になりました。
Java EE 6になり、web.xmlを一切書かなくても今までできたことができるのかは調べていませんが、近いうちに確認してみようかと思います。あの設定は厳しいだろうというのも少しありますので。

内容的には、Base64エンコードされたファイルをデコードするために、commons codecを使用しました。デコードしたバイト配列を単純に、受け取ったファイル名でファイルとして保管してアップロードが完了となります。