前回WebSocketを少しいじったので、今回は少し拡張してファイルアップロードを実現してみました。
まずサーバ側はファイル名を受け取るようにしてみました。ちと面倒だったのでテキストメッセージでファイル名を受けたときにファイルをオープンして、ファイルのクローズは切断時に行ってます。(ちなみにGlassFish上で動作させてます。)
--------------------------------------------------
package sample;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.websocket.OnOpen;
import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
@ServerEndpoint("/endpoint")
public class NewWSEndpoint {
private static FileChannel channel = null;
@OnOpen
public void onOpen(Session session){
System.out.println("OnOpen");
}
@OnClose
public void onClose(Session session){
try {
System.out.println("OnClose");
channel.close();
} catch (IOException ex) {
Logger.getLogger(NewWSEndpoint.class.getName()).log(Level.SEVERE, null, ex);
}
}
@OnMessage
public String onMessage(Session session, String message) {
try {
System.out.println("OnMessage String = " + message);
channel = new FileOutputStream(new File("../logs/" + message)).getChannel();
} catch (FileNotFoundException ex) {
Logger.getLogger(NewWSEndpoint.class.getName()).log(Level.SEVERE, null, ex);
}
return null;
}
@OnMessage
public void onMessage(Session session, ByteBuffer byteBuffer) {
try {
System.out.println("OnMessage binary = " + byteBuffer.toString());
channel.write(byteBuffer);
} catch (IOException ex) {
Logger.getLogger(NewWSEndpoint.class.getName()).log(Level.SEVERE, null, ex);
}
}
@OnError
public void onError(Throwable t) {
System.out.println("OnError");
}
}
--------------------------------------------------
HTMLはシンプルにこんな感じ。
ファイルをドラッグ&ドロップして指定する形を取りました。
--------------------------------------------------
JavaEE7 WebSocket Test
--------------------------------------------------
JavaScriptはこんな感じ。
指定されたファイルを読み込みバイナリとして送信します。
--------------------------------------------------
if (!window.File) {
window.alert("このブラウザではFile APIが使えません");
}
function onDrop(event) {
var files = event.dataTransfer.files;
var disp = document.getElementById("disp");
for (var i = 0; i < files.length; i++) {
var f = files[i];
var socket = new WebSocket("ws://localhost:8080/TestWebSocket/endpoint");
socket.onopen = function() {
var reader = new FileReader();
reader.onload = function(){
var binary = new Uint8Array(reader.result);
socket.send(f.name);
socket.send(binary.buffer);
socket.close();
disp.innerHTML = f.name + "[" + f.size + "byte]" + "アップロード完了";
};
reader.readAsArrayBuffer(f);
};
}
event.preventDefault();
}
function onDragOver(event) {
event.preventDefault();
}
--------------------------------------------------
あとは大きなファイルでも経過を表示したりできるように分割送信とかするといいでしょうね。