基于html5 websocket API简单实现断点上传文件

来源:互联网 发布:男人花网络女主播是谁 编辑:程序博客网 时间:2024/06/11 21:09

本实例只是简单地实现文件的断点上传功能,有更好的建议请不吝赐教


本实例基于html5的 websocket API和netty框架,如果您对两个技术不太熟悉,可以点击下面连接了解

websocket: http://www.chinaz.com/web/2012/0806/267188.shtml

                      http://www.websocket.org/

netty:             https://netty.io/

netty jar包:http://download.csdn.net/detail/wudasong_/4650052

准备:

fiefox浏览器或chrome浏览器

在classpath中导入netty类库,json类库

好拉,一切准备就绪...

服务器端:

WebSocketServerInitializer.java

/* * Copyright 2012 The Netty Project * * The Netty Project licenses this file to you under the Apache License, * version 2.0 (the "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at: * *   http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations * under the License. */package com.wudasong.breakPoinUploadServer;import io.netty.bootstrap.ServerBootstrap;import io.netty.channel.Channel;import io.netty.channel.socket.nio.NioEventLoop;import io.netty.channel.socket.nio.NioServerSocketChannel;/** * A HTTP server which serves Web Socket requests at: * * http://localhost:8080/websocket * * Open your browser at http://localhost:8080/, then the demo page will be loaded and a Web Socket connection will be * made automatically. * * This server illustrates support for the different web socket specification versions and will work with: * * <ul> * <li>Safari 5+ (draft-ietf-hybi-thewebsocketprotocol-00) * <li>Chrome 6-13 (draft-ietf-hybi-thewebsocketprotocol-00) * <li>Chrome 14+ (draft-ietf-hybi-thewebsocketprotocol-10) * <li>Chrome 16+ (RFC 6455 aka draft-ietf-hybi-thewebsocketprotocol-17) * <li>Firefox 7+ (draft-ietf-hybi-thewebsocketprotocol-10) * <li>Firefox 11+ (RFC 6455 aka draft-ietf-hybi-thewebsocketprotocol-17) * </ul> */public class WebSocketServer {    private final int port;    public WebSocketServer(int port) {        this.port = port;    }    public void run() throws Exception {        ServerBootstrap b = new ServerBootstrap();        try {            b.eventLoop(new NioEventLoop(), new NioEventLoop())             .channel(new NioServerSocketChannel())             .localAddress(port)             .childHandler(new WebSocketServerInitializer());            Channel ch = b.bind().sync().channel();            System.out.println("Web socket server started at port " + port + '.');            System.out.println("Open your browser and navigate to http://localhost:" + port + '/');            ch.closeFuture().sync();        } finally {            b.shutdown();        }    }    public static void main(String[] args) throws Exception {        int port;        if (args.length > 0) {            port = Integer.parseInt(args[0]);        } else {            port = 8082;        }        new WebSocketServer(port).run();    }}

WebSocketServerHandler.java

package com.wudasong.breakPoinUploadServer;import static io.netty.handler.codec.http.HttpHeaders.*;import static io.netty.handler.codec.http.HttpHeaders.Names.CONTENT_TYPE;import static io.netty.handler.codec.http.HttpMethod.*;import static io.netty.handler.codec.http.HttpResponseStatus.*;import static io.netty.handler.codec.http.HttpVersion.*;import java.io.File;import java.io.IOException;import java.io.RandomAccessFile;import java.nio.ByteBuffer;import java.nio.channels.FileChannel;import org.json.JSONException;import org.json.JSONObject;import io.netty.buffer.Unpooled;import io.netty.channel.ChannelFuture;import io.netty.channel.ChannelFutureListener;import io.netty.channel.ChannelHandlerContext;import io.netty.channel.ChannelInboundMessageHandlerAdapter;import io.netty.handler.codec.http.DefaultHttpResponse;import io.netty.handler.codec.http.HttpHeaders;import io.netty.handler.codec.http.HttpRequest;import io.netty.handler.codec.http.HttpResponse;import io.netty.handler.codec.http.HttpResponseStatus;import io.netty.handler.codec.http.websocketx.BinaryWebSocketFrame;import io.netty.handler.codec.http.websocketx.CloseWebSocketFrame;import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;import io.netty.handler.codec.http.websocketx.WebSocketFrame;import io.netty.handler.codec.http.websocketx.WebSocketServerHandshaker;import io.netty.handler.codec.http.websocketx.WebSocketServerHandshakerFactory;import io.netty.util.CharsetUtil;/** * Handles handshakes and messages */public class WebSocketServerHandler extends ChannelInboundMessageHandlerAdapter<Object> {private static final String WEBSOCKET_PATH = "/websocket";private static final long BLOCK_SIZE=1024*65L;private static final int BYTE_BUFFER_SIZE=1024*65;private static final String SERVER_SAVE_PATH="D:\\fileUpload\\";private long startByte=0;private long stopByte=0;private JSONObject fileInfo;private WebSocketServerHandshaker handshaker;@Overridepublic void messageReceived(ChannelHandlerContext ctx, Object msg) throws Exception {if (msg instanceof HttpRequest) {handleHttpRequest(ctx, (HttpRequest) msg);} else if (msg instanceof WebSocketFrame) {handleWebSocketFrame(ctx, (WebSocketFrame) msg);}}private void handleHttpRequest(ChannelHandlerContext ctx, HttpRequest req) throws Exception {// Allow only GET methods.if (req.getMethod() != GET) {sendHttpResponse(ctx, req, new DefaultHttpResponse(HTTP_1_1, FORBIDDEN));return;}// HandshakeWebSocketServerHandshakerFactory wsFactory = new WebSocketServerHandshakerFactory(getWebSocketLocation(req), null, false,1048576);handshaker = wsFactory.newHandshaker(req);if (handshaker == null) {wsFactory.sendUnsupportedWebSocketVersionResponse(ctx.channel());} else {handshaker.handshake(ctx.channel(), req);}}private void handleWebSocketFrame(ChannelHandlerContext ctx, WebSocketFrame frame) throws JSONException, IOException {// Check for closing frameif (frame instanceof CloseWebSocketFrame) {handshaker.close(ctx.channel(), (CloseWebSocketFrame) frame);return;} else if(frame instanceof TextWebSocketFrame){TextWebSocketFrame message=(TextWebSocketFrame)frame;fileInfo=new JSONObject(message.getText());System.out.println("上传的文件名:\t"+fileInfo.getString("name")+"\n文件大小:\t"+fileInfo.getLong("size")+"\n最后修改时间:\t"+fileInfo.getString("lastModifiedDate"));JSONObject message4client=new JSONObject();File file = new File(SERVER_SAVE_PATH+fileInfo.getString("name"));long fileSize=fileInfo.getLong("size");if(file.createNewFile()){stopByte=BLOCK_SIZE;message4client.put("startByte", 0);if(stopByte<fileSize){message4client.put("stopByte", stopByte);}else {message4client.put("stopByte", fileSize);}message4client.put("complete", false);}else {startByte=file.length();stopByte=startByte+BLOCK_SIZE;if(startByte>=fileInfo.getLong("size")){message4client.put("startByte", 0);message4client.put("stopByte", 0);message4client.put("complete", true);}if(stopByte<fileSize){message4client.put("startByte", startByte);message4client.put("stopByte", stopByte);message4client.put("complete", false);}else {message4client.put("startByte", startByte);message4client.put("stopByte", fileSize);message4client.put("complete", false);}}ctx.channel().write(new TextWebSocketFrame(message4client.toString()));}else if(frame instanceof BinaryWebSocketFrame){BinaryWebSocketFrame binaryFrame=(BinaryWebSocketFrame)frame;File file = new File(SERVER_SAVE_PATH+fileInfo.getString("name"));long fileSize=fileInfo.getLong("size");if(stopByte>=fileSize){stopByte=fileSize;}JSONObject message4client=new JSONObject();if(startByte>=fileInfo.getLong("size")){message4client.put("startByte", 0);message4client.put("stopByte", 0);message4client.put("complete", true);ctx.channel().write(new TextWebSocketFrame(message4client.toString()));}FileChannel fileChannel=new RandomAccessFile(file, "rw").getChannel();fileChannel.position(fileChannel.size());if(stopByte<fileSize){ByteBuffer byteBuffer=ByteBuffer.allocate(BYTE_BUFFER_SIZE);byteBuffer.clear();byteBuffer.put(binaryFrame.getBinaryData().array());byteBuffer.flip();fileChannel.write(byteBuffer);fileChannel.close();startByte=stopByte;stopByte=startByte+BLOCK_SIZE;message4client.put("startByte", startByte);message4client.put("stopByte", stopByte);message4client.put("complete", false);ctx.channel().write(new TextWebSocketFrame(message4client.toString()));}else {ByteBuffer byteBuffer=ByteBuffer.allocate(binaryFrame.getBinaryData().capacity());byteBuffer.clear();byteBuffer.put(binaryFrame.getBinaryData().array());byteBuffer.flip();fileChannel.write(byteBuffer);fileChannel.close();message4client.put("startByte", 0);message4client.put("stopByte", 0);message4client.put("complete", true);ctx.channel().write(new TextWebSocketFrame(message4client.toString()));}}}private static void sendHttpResponse(ChannelHandlerContext ctx, HttpRequest req, HttpResponse res) {// Generate an error page if response status code is not OK (200).if (res.getStatus().getCode() != 200) {res.setContent(Unpooled.copiedBuffer(res.getStatus().toString(), CharsetUtil.UTF_8));setContentLength(res, res.getContent().readableBytes());}// Send the response and close the connection if necessary.ChannelFuture f = ctx.channel().write(res);if (!isKeepAlive(req) || res.getStatus().getCode() != 200) {f.addListener(ChannelFutureListener.CLOSE);}}private static void sendError(ChannelHandlerContext ctx, HttpResponseStatus status) {HttpResponse response = new DefaultHttpResponse(HTTP_1_1, status);response.setHeader(CONTENT_TYPE, "text/plain; charset=UTF-8");response.setContent(Unpooled.copiedBuffer("Failure: " + status.toString() + "\r\n",CharsetUtil.UTF_8));ctx.write(response).addListener(ChannelFutureListener.CLOSE);}@Overridepublic void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {cause.printStackTrace();ctx.close();}private static String getWebSocketLocation(HttpRequest req) {return "ws://" + req.getHeader(HttpHeaders.Names.HOST) + WEBSOCKET_PATH;}}

WebServerSocket.java

/* * Copyright 2012 The Netty Project * * The Netty Project licenses this file to you under the Apache License, * version 2.0 (the "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at: * *   http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations * under the License. */package com.wudasong.breakPoinUploadServer;import io.netty.bootstrap.ServerBootstrap;import io.netty.channel.Channel;import io.netty.channel.socket.nio.NioEventLoop;import io.netty.channel.socket.nio.NioServerSocketChannel;/** * A HTTP server which serves Web Socket requests at: * * http://localhost:8080/websocket * * Open your browser at http://localhost:8080/, then the demo page will be loaded and a Web Socket connection will be * made automatically. * * This server illustrates support for the different web socket specification versions and will work with: * * <ul> * <li>Safari 5+ (draft-ietf-hybi-thewebsocketprotocol-00) * <li>Chrome 6-13 (draft-ietf-hybi-thewebsocketprotocol-00) * <li>Chrome 14+ (draft-ietf-hybi-thewebsocketprotocol-10) * <li>Chrome 16+ (RFC 6455 aka draft-ietf-hybi-thewebsocketprotocol-17) * <li>Firefox 7+ (draft-ietf-hybi-thewebsocketprotocol-10) * <li>Firefox 11+ (RFC 6455 aka draft-ietf-hybi-thewebsocketprotocol-17) * </ul> */public class WebSocketServer {    private final int port;    public WebSocketServer(int port) {        this.port = port;    }    public void run() throws Exception {        ServerBootstrap b = new ServerBootstrap();        try {            b.eventLoop(new NioEventLoop(), new NioEventLoop())             .channel(new NioServerSocketChannel())             .localAddress(port)             .childHandler(new WebSocketServerInitializer());            Channel ch = b.bind().sync().channel();            System.out.println("Web socket server started at port " + port + '.');            System.out.println("Open your browser and navigate to http://localhost:" + port + '/');            ch.closeFuture().sync();        } finally {            b.shutdown();        }    }    public static void main(String[] args) throws Exception {        int port;        if (args.length > 0) {            port = Integer.parseInt(args[0]);        } else {            port = 8082;        }        new WebSocketServer(port).run();    }}


客户端代码:

MyHtml.html

<!DOCTYPE html><html><head><title>MyHtml.html</title><meta http-equiv="keywords" content="keyword1,keyword2,keyword3"><meta http-equiv="description" content="this is my page"><meta http-equiv="content-type" content="text/html; charset=UTF-8"></head><body><input type="file" id="files" name="file" /><input type="button" id="upload" value="上传" /><input type="button" id="stop" value="暂停" /><script type="text/javascript" src="upload.js"></script></body></html>

upload.js

var socket;//openSocket("ws://localhost:8082/websocket");document.getElementById("stop").addEventListener("click", function(){socket.close();}, false);document.getElementById("upload").addEventListener("click", function(){openSocket("ws://localhost:8082/websocket");setTimeout(function(){fileUpload();}, 500);}, false);function openSocket(url){if(!window.WebSocket){window.WebSocket=window.MozWebSocket;} if(window.WebSocket){socket=new WebSocket(url);//socket=new WebSocket("ws://localhost:8082/websocket");socket.onopen=onOpen;socket.onclose=onClose;}else {alert("your browser does not support websocket");}};function onOpen(event){console.log("websocket is opened");}function onClose(event){console.log("websocket is closed");}function fileUpload(){var files = document.getElementById('files').files;if (!files.length) {alert('Please select a file!');return;}var file = files[0];var fileInfo={"opcode":1,"name":file.name,"size":file.size,"lastModifiedDate":file.lastModifiedDate};//console.log(JSON.stringify(fileInfo));send(JSON.stringify(fileInfo));socket.onmessage=function(event){var startStop=JSON.parse(event.data);if(startStop.startByte===startStop.stopByte||startStop.complete){console.log(startStop);alert("文件上传成功!");}else {console.log(startStop);readBlob(files,startStop.startByte, startStop.stopByte);}};}function send(message){if(!window.WebSocket){return;}if(socket.readyState==WebSocket.OPEN){socket.send(message);}else{console.log("the socket is not open");}}function readBlob(files,opt_startByte, opt_stopByte) {if (!files.length) {alert('Please select a file!');return;}var file = files[0];var start = parseInt(opt_startByte) || 0;var stop = parseInt(opt_stopByte) || file.size - 1;var reader = new FileReader();if (file.webkitSlice) {var blob = file.webkitSlice(start, stop);} else if (file.mozSlice) {var blob = file.mozSlice(start, stop);}reader.readAsArrayBuffer(blob);reader.onloadend = function(evt) {if (evt.target.readyState == FileReader.DONE) { // DONE == 2send(reader.result);}};}

搞定..

求多多指教!!

原创粉丝点击