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

来源:互联网 发布:网络直播要哪些设备 编辑:程序博客网 时间:2024/06/08 00:55

本实例基于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

[java] view plain copy
  1. /* 
  2.  * Copyright 2012 The Netty Project 
  3.  * 
  4.  * The Netty Project licenses this file to you under the Apache License, 
  5.  * version 2.0 (the "License"); you may not use this file except in compliance 
  6.  * with the License. You may obtain a copy of the License at: 
  7.  * 
  8.  *   http://www.apache.org/licenses/LICENSE-2.0 
  9.  * 
  10.  * Unless required by applicable law or agreed to in writing, software 
  11.  * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 
  12.  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 
  13.  * License for the specific language governing permissions and limitations 
  14.  * under the License. 
  15.  */  
  16. package com.wudasong.breakPoinUploadServer;  
  17.   
  18. import io.netty.bootstrap.ServerBootstrap;  
  19. import io.netty.channel.Channel;  
  20. import io.netty.channel.socket.nio.NioEventLoop;  
  21. import io.netty.channel.socket.nio.NioServerSocketChannel;  
  22.   
  23. /** 
  24.  * A HTTP server which serves Web Socket requests at: 
  25.  * 
  26.  * http://localhost:8080/websocket 
  27.  * 
  28.  * Open your browser at http://localhost:8080/, then the demo page will be loaded and a Web Socket connection will be 
  29.  * made automatically. 
  30.  * 
  31.  * This server illustrates support for the different web socket specification versions and will work with: 
  32.  * 
  33.  * <ul> 
  34.  * <li>Safari 5+ (draft-ietf-hybi-thewebsocketprotocol-00) 
  35.  * <li>Chrome 6-13 (draft-ietf-hybi-thewebsocketprotocol-00) 
  36.  * <li>Chrome 14+ (draft-ietf-hybi-thewebsocketprotocol-10) 
  37.  * <li>Chrome 16+ (RFC 6455 aka draft-ietf-hybi-thewebsocketprotocol-17) 
  38.  * <li>Firefox 7+ (draft-ietf-hybi-thewebsocketprotocol-10) 
  39.  * <li>Firefox 11+ (RFC 6455 aka draft-ietf-hybi-thewebsocketprotocol-17) 
  40.  * </ul> 
  41.  */  
  42. public class WebSocketServer {  
  43.   
  44.     private final int port;  
  45.   
  46.     public WebSocketServer(int port) {  
  47.         this.port = port;  
  48.     }  
  49.   
  50.     public void run() throws Exception {  
  51.         ServerBootstrap b = new ServerBootstrap();  
  52.         try {  
  53.             b.eventLoop(new NioEventLoop(), new NioEventLoop())  
  54.              .channel(new NioServerSocketChannel())  
  55.              .localAddress(port)  
  56.              .childHandler(new WebSocketServerInitializer());  
  57.   
  58.             Channel ch = b.bind().sync().channel();  
  59.             System.out.println("Web socket server started at port " + port + '.');  
  60.             System.out.println("Open your browser and navigate to http://localhost:" + port + '/');  
  61.   
  62.             ch.closeFuture().sync();  
  63.         } finally {  
  64.             b.shutdown();  
  65.         }  
  66.     }  
  67.   
  68.     public static void main(String[] args) throws Exception {  
  69.         int port;  
  70.         if (args.length > 0) {  
  71.             port = Integer.parseInt(args[0]);  
  72.         } else {  
  73.             port = 8082;  
  74.         }  
  75.         new WebSocketServer(port).run();  
  76.     }  
  77. }  

WebSocketServerHandler.java

[java] view plain copy
  1. package com.wudasong.breakPoinUploadServer;  
  2.   
  3. import static io.netty.handler.codec.http.HttpHeaders.*;  
  4. import static io.netty.handler.codec.http.HttpHeaders.Names.CONTENT_TYPE;  
  5. import static io.netty.handler.codec.http.HttpMethod.*;  
  6. import static io.netty.handler.codec.http.HttpResponseStatus.*;  
  7. import static io.netty.handler.codec.http.HttpVersion.*;  
  8.   
  9. import java.io.File;  
  10. import java.io.IOException;  
  11. import java.io.RandomAccessFile;  
  12. import java.nio.ByteBuffer;  
  13. import java.nio.channels.FileChannel;  
  14.   
  15. import org.json.JSONException;  
  16. import org.json.JSONObject;  
  17.   
  18. import io.netty.buffer.Unpooled;  
  19. import io.netty.channel.ChannelFuture;  
  20. import io.netty.channel.ChannelFutureListener;  
  21. import io.netty.channel.ChannelHandlerContext;  
  22. import io.netty.channel.ChannelInboundMessageHandlerAdapter;  
  23. import io.netty.handler.codec.http.DefaultHttpResponse;  
  24. import io.netty.handler.codec.http.HttpHeaders;  
  25. import io.netty.handler.codec.http.HttpRequest;  
  26. import io.netty.handler.codec.http.HttpResponse;  
  27. import io.netty.handler.codec.http.HttpResponseStatus;  
  28. import io.netty.handler.codec.http.websocketx.BinaryWebSocketFrame;  
  29. import io.netty.handler.codec.http.websocketx.CloseWebSocketFrame;  
  30. import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;  
  31. import io.netty.handler.codec.http.websocketx.WebSocketFrame;  
  32. import io.netty.handler.codec.http.websocketx.WebSocketServerHandshaker;  
  33. import io.netty.handler.codec.http.websocketx.WebSocketServerHandshakerFactory;  
  34. import io.netty.util.CharsetUtil;  
  35.   
  36. /** 
  37.  * Handles handshakes and messages 
  38.  */  
  39. public class WebSocketServerHandler extends ChannelInboundMessageHandlerAdapter<Object> {  
  40.   
  41.     private static final String WEBSOCKET_PATH = "/websocket";  
  42.   
  43.     private static final long BLOCK_SIZE=1024*65L;  
  44.     private static final int BYTE_BUFFER_SIZE=1024*65;  
  45.     private static final String SERVER_SAVE_PATH="D:\\fileUpload\\";  
  46.   
  47.     private long startByte=0;  
  48.     private long stopByte=0;  
  49.     private JSONObject fileInfo;  
  50.     private WebSocketServerHandshaker handshaker;  
  51.   
  52.     @Override  
  53.     public void messageReceived(ChannelHandlerContext ctx, Object msg) throws Exception {  
  54.         if (msg instanceof HttpRequest) {  
  55.             handleHttpRequest(ctx, (HttpRequest) msg);  
  56.         } else if (msg instanceof WebSocketFrame) {  
  57.             handleWebSocketFrame(ctx, (WebSocketFrame) msg);  
  58.         }  
  59.     }  
  60.   
  61.     private void handleHttpRequest(ChannelHandlerContext ctx, HttpRequest req) throws Exception {  
  62.         // Allow only GET methods.  
  63.         if (req.getMethod() != GET) {  
  64.             sendHttpResponse(ctx, req, new DefaultHttpResponse(HTTP_1_1, FORBIDDEN));  
  65.             return;  
  66.         }  
  67.         // Handshake  
  68.         WebSocketServerHandshakerFactory wsFactory = new WebSocketServerHandshakerFactory(  
  69.                 getWebSocketLocation(req), nullfalse,1048576);  
  70.         handshaker = wsFactory.newHandshaker(req);  
  71.         if (handshaker == null) {  
  72.             wsFactory.sendUnsupportedWebSocketVersionResponse(ctx.channel());  
  73.         } else {  
  74.             handshaker.handshake(ctx.channel(), req);  
  75.         }  
  76.     }  
  77.   
  78.     private void handleWebSocketFrame(ChannelHandlerContext ctx, WebSocketFrame frame) throws JSONException, IOException {  
  79.   
  80.         // Check for closing frame  
  81.         if (frame instanceof CloseWebSocketFrame) {  
  82.             handshaker.close(ctx.channel(), (CloseWebSocketFrame) frame);  
  83.             return;  
  84.         } else if(frame instanceof TextWebSocketFrame){  
  85.             TextWebSocketFrame message=(TextWebSocketFrame)frame;  
  86.             fileInfo=new JSONObject(message.getText());  
  87.             System.out.println("上传的文件名:\t"+fileInfo.getString("name")+  
  88.                     "\n文件大小:\t"+fileInfo.getLong("size")+  
  89.                     "\n最后修改时间:\t"+fileInfo.getString("lastModifiedDate"));  
  90.             JSONObject message4client=new JSONObject();  
  91.             File file = new File(SERVER_SAVE_PATH+fileInfo.getString("name"));  
  92.             long fileSize=fileInfo.getLong("size");  
  93.             if(file.createNewFile()){  
  94.                 stopByte=BLOCK_SIZE;  
  95.                 message4client.put("startByte"0);  
  96.                 if(stopByte<fileSize){  
  97.                     message4client.put("stopByte", stopByte);  
  98.                 }else {  
  99.                     message4client.put("stopByte", fileSize);  
  100.                 }  
  101.                 message4client.put("complete"false);  
  102.             }else {  
  103.                 startByte=file.length();  
  104.                 stopByte=startByte+BLOCK_SIZE;  
  105.                 if(startByte>=fileInfo.getLong("size")){  
  106.                     message4client.put("startByte"0);  
  107.                     message4client.put("stopByte"0);  
  108.                     message4client.put("complete"true);  
  109.                 }  
  110.                 if(stopByte<fileSize){  
  111.                     message4client.put("startByte", startByte);  
  112.                     message4client.put("stopByte", stopByte);  
  113.                     message4client.put("complete"false);  
  114.                 }else {  
  115.                     message4client.put("startByte", startByte);  
  116.                     message4client.put("stopByte", fileSize);  
  117.                     message4client.put("complete"false);  
  118.                 }  
  119.             }  
  120.             ctx.channel().write(new TextWebSocketFrame(message4client.toString()));  
  121.         }else if(frame instanceof BinaryWebSocketFrame){  
  122.             BinaryWebSocketFrame binaryFrame=(BinaryWebSocketFrame)frame;  
  123.             File file = new File(SERVER_SAVE_PATH+fileInfo.getString("name"));  
  124.             long fileSize=fileInfo.getLong("size");  
  125.             if(stopByte>=fileSize){  
  126.                 stopByte=fileSize;  
  127.             }  
  128.             JSONObject message4client=new JSONObject();  
  129.             if(startByte>=fileInfo.getLong("size")){  
  130.                 message4client.put("startByte"0);  
  131.                 message4client.put("stopByte"0);  
  132.                 message4client.put("complete"true);  
  133.                 ctx.channel().write(new TextWebSocketFrame(message4client.toString()));  
  134.             }  
  135.             FileChannel fileChannel=new RandomAccessFile(file, "rw").getChannel();  
  136.             fileChannel.position(fileChannel.size());  
  137.   
  138.   
  139.             if(stopByte<fileSize){  
  140.                 ByteBuffer byteBuffer=ByteBuffer.allocate(BYTE_BUFFER_SIZE);  
  141.                 byteBuffer.clear();  
  142.                 byteBuffer.put(binaryFrame.getBinaryData().array());  
  143.                 byteBuffer.flip();  
  144.                 fileChannel.write(byteBuffer);  
  145.                 fileChannel.close();  
  146.                 startByte=stopByte;  
  147.                 stopByte=startByte+BLOCK_SIZE;  
  148.                 message4client.put("startByte", startByte);  
  149.                 message4client.put("stopByte", stopByte);  
  150.                 message4client.put("complete"false);  
  151.                 ctx.channel().write(new TextWebSocketFrame(message4client.toString()));  
  152.             }else {  
  153.                 ByteBuffer byteBuffer=ByteBuffer.allocate(binaryFrame.getBinaryData().capacity());  
  154.                 byteBuffer.clear();  
  155.                 byteBuffer.put(binaryFrame.getBinaryData().array());  
  156.                 byteBuffer.flip();  
  157.                 fileChannel.write(byteBuffer);  
  158.                 fileChannel.close();  
  159.                 message4client.put("startByte"0);  
  160.                 message4client.put("stopByte"0);  
  161.                 message4client.put("complete"true);  
  162.                 ctx.channel().write(new TextWebSocketFrame(message4client.toString()));  
  163.             }  
  164.         }  
  165.     }  
  166.   
  167.     private static void sendHttpResponse(ChannelHandlerContext ctx, HttpRequest req, HttpResponse res) {  
  168.         // Generate an error page if response status code is not OK (200).  
  169.         if (res.getStatus().getCode() != 200) {  
  170.             res.setContent(Unpooled.copiedBuffer(res.getStatus().toString(), CharsetUtil.UTF_8));  
  171.             setContentLength(res, res.getContent().readableBytes());  
  172.         }  
  173.   
  174.         // Send the response and close the connection if necessary.  
  175.         ChannelFuture f = ctx.channel().write(res);  
  176.         if (!isKeepAlive(req) || res.getStatus().getCode() != 200) {  
  177.             f.addListener(ChannelFutureListener.CLOSE);  
  178.         }  
  179.     }  
  180.   
  181.     private static void sendError(ChannelHandlerContext ctx, HttpResponseStatus status) {  
  182.         HttpResponse response = new DefaultHttpResponse(HTTP_1_1, status);  
  183.         response.setHeader(CONTENT_TYPE, "text/plain; charset=UTF-8");  
  184.         response.setContent(Unpooled.copiedBuffer(  
  185.                 "Failure: " + status.toString() + "\r\n",  
  186.                 CharsetUtil.UTF_8));  
  187.         ctx.write(response).addListener(ChannelFutureListener.CLOSE);  
  188.     }  
  189.   
  190.     @Override  
  191.     public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {  
  192.         cause.printStackTrace();  
  193.         ctx.close();  
  194.     }  
  195.   
  196.     private static String getWebSocketLocation(HttpRequest req) {  
  197.         return "ws://" + req.getHeader(HttpHeaders.Names.HOST) + WEBSOCKET_PATH;  
  198.     }  
  199. }  

WebServerSocket.java

[java] view plain copy
  1. /* 
  2.  * Copyright 2012 The Netty Project 
  3.  * 
  4.  * The Netty Project licenses this file to you under the Apache License, 
  5.  * version 2.0 (the "License"); you may not use this file except in compliance 
  6.  * with the License. You may obtain a copy of the License at: 
  7.  * 
  8.  *   http://www.apache.org/licenses/LICENSE-2.0 
  9.  * 
  10.  * Unless required by applicable law or agreed to in writing, software 
  11.  * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 
  12.  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 
  13.  * License for the specific language governing permissions and limitations 
  14.  * under the License. 
  15.  */  
  16. package com.wudasong.breakPoinUploadServer;  
  17.   
  18. import io.netty.bootstrap.ServerBootstrap;  
  19. import io.netty.channel.Channel;  
  20. import io.netty.channel.socket.nio.NioEventLoop;  
  21. import io.netty.channel.socket.nio.NioServerSocketChannel;  
  22.   
  23. /** 
  24.  * A HTTP server which serves Web Socket requests at: 
  25.  * 
  26.  * http://localhost:8080/websocket 
  27.  * 
  28.  * Open your browser at http://localhost:8080/, then the demo page will be loaded and a Web Socket connection will be 
  29.  * made automatically. 
  30.  * 
  31.  * This server illustrates support for the different web socket specification versions and will work with: 
  32.  * 
  33.  * <ul> 
  34.  * <li>Safari 5+ (draft-ietf-hybi-thewebsocketprotocol-00) 
  35.  * <li>Chrome 6-13 (draft-ietf-hybi-thewebsocketprotocol-00) 
  36.  * <li>Chrome 14+ (draft-ietf-hybi-thewebsocketprotocol-10) 
  37.  * <li>Chrome 16+ (RFC 6455 aka draft-ietf-hybi-thewebsocketprotocol-17) 
  38.  * <li>Firefox 7+ (draft-ietf-hybi-thewebsocketprotocol-10) 
  39.  * <li>Firefox 11+ (RFC 6455 aka draft-ietf-hybi-thewebsocketprotocol-17) 
  40.  * </ul> 
  41.  */  
  42. public class WebSocketServer {  
  43.   
  44.     private final int port;  
  45.   
  46.     public WebSocketServer(int port) {  
  47.         this.port = port;  
  48.     }  
  49.   
  50.     public void run() throws Exception {  
  51.         ServerBootstrap b = new ServerBootstrap();  
  52.         try {  
  53.             b.eventLoop(new NioEventLoop(), new NioEventLoop())  
  54.              .channel(new NioServerSocketChannel())  
  55.              .localAddress(port)  
  56.              .childHandler(new WebSocketServerInitializer());  
  57.   
  58.             Channel ch = b.bind().sync().channel();  
  59.             System.out.println("Web socket server started at port " + port + '.');  
  60.             System.out.println("Open your browser and navigate to http://localhost:" + port + '/');  
  61.   
  62.             ch.closeFuture().sync();  
  63.         } finally {  
  64.             b.shutdown();  
  65.         }  
  66.     }  
  67.   
  68.     public static void main(String[] args) throws Exception {  
  69.         int port;  
  70.         if (args.length > 0) {  
  71.             port = Integer.parseInt(args[0]);  
  72.         } else {  
  73.             port = 8082;  
  74.         }  
  75.         new WebSocketServer(port).run();  
  76.     }  
  77. }  


客户端代码:

MyHtml.html

[html] view plain copy
  1. <!DOCTYPE html>  
  2. <html>  
  3. <head>  
  4. <title>MyHtml.html</title>  
  5.   
  6. <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">  
  7. <meta http-equiv="description" content="this is my page">  
  8. <meta http-equiv="content-type" content="text/html; charset=UTF-8">  
  9.   
  10.   
  11. </head>  
  12.   
  13. <body>  
  14.     <input type="file" id="files" name="file" />  
  15.     <input type="button" id="upload" value="上传" />  
  16.     <input type="button" id="stop" value="暂停" />  
  17.     <script type="text/javascript" src="upload.js"></script>  
  18. </body>  
  19. </html>  

upload.js

[javascript] view plain copy
  1. var socket;  
  2. //openSocket("ws://localhost:8082/websocket");  
  3.   
  4. document.getElementById("stop").addEventListener("click"function(){  
  5.     socket.close();  
  6. }, false);  
  7.   
  8. document.getElementById("upload").addEventListener("click"function(){  
  9.     openSocket("ws://localhost:8082/websocket");  
  10.     setTimeout(function(){  
  11.         fileUpload();  
  12.     }, 500);  
  13. }, false);  
  14.   
  15. function openSocket(url){  
  16.     if(!window.WebSocket){  
  17.         window.WebSocket=window.MozWebSocket;  
  18.     }   
  19.     if(window.WebSocket){  
  20.         socket=new WebSocket(url);  
  21. //      socket=new WebSocket("ws://localhost:8082/websocket");  
  22.         socket.onopen=onOpen;  
  23.         socket.onclose=onClose;  
  24.     }else {  
  25.         alert("your browser does not support websocket");  
  26.     }  
  27. };  
  28.   
  29. function onOpen(event){  
  30.     console.log("websocket is opened");  
  31. }  
  32.   
  33. function onClose(event){  
  34.     console.log("websocket is closed");  
  35. }  
  36.   
  37. function fileUpload(){  
  38.     var files = document.getElementById('files').files;  
  39.     if (!files.length) {  
  40.         alert('Please select a file!');  
  41.         return;  
  42.     }  
  43.     var file = files[0];  
  44.     var fileInfo={  
  45.             "opcode":1,  
  46.             "name":file.name,  
  47.             "size":file.size,  
  48.             "lastModifiedDate":file.lastModifiedDate  
  49.     };  
  50. //  console.log(JSON.stringify(fileInfo));  
  51.     send(JSON.stringify(fileInfo));  
  52.     socket.onmessage=function(event){  
  53.         var startStop=JSON.parse(event.data);  
  54.         if(startStop.startByte===startStop.stopByte||startStop.complete){  
  55.             console.log(startStop);  
  56.             alert("文件上传成功!");  
  57.         }else {  
  58.             console.log(startStop);  
  59.             readBlob(files,startStop.startByte, startStop.stopByte);  
  60.         }  
  61.     };  
  62. }  
  63.   
  64. function send(message){  
  65.     if(!window.WebSocket){  
  66.         return;  
  67.     }  
  68.     if(socket.readyState==WebSocket.OPEN){  
  69.         socket.send(message);  
  70.     }else{  
  71.         console.log("the socket is not open");  
  72.     }  
  73. }  
  74.   
  75. function readBlob(files,opt_startByte, opt_stopByte) {  
  76.     if (!files.length) {  
  77.         alert('Please select a file!');  
  78.         return;  
  79.     }  
  80.     var file = files[0];  
  81.     var start = parseInt(opt_startByte) || 0;  
  82.     var stop = parseInt(opt_stopByte) || file.size - 1;  
  83.   
  84.     var reader = new FileReader();  
  85.     if (file.webkitSlice) {  
  86.         var blob = file.webkitSlice(start, stop);  
  87.     } else if (file.mozSlice) {  
  88.         var blob = file.mozSlice(start, stop);  
  89.     }  
  90.     reader.readAsArrayBuffer(blob);  
  91.     reader.onloadend = function(evt) {  
  92.         if (evt.target.readyState == FileReader.DONE) { // DONE == 2  
  93.             send(reader.result);  
  94.         }  
  95.     };  
原创粉丝点击