2014-02-18 50 views
2

我幾乎沒有做websocket文件上傳功能。但上傳速度似乎很慢。我已經使用Java API for websocket Server和javascript for client。Websocket文件上傳速度問題(Java websocket API和Javascript)

服務器:

package websocket; 

import java.io.File; 
import java.io.FileNotFoundException; 
import java.io.FileOutputStream; 
import java.io.IOException; 
import java.nio.ByteBuffer; 

import javax.websocket.CloseReason; 
import javax.websocket.EndpointConfig; 
import javax.websocket.OnClose; 
import javax.websocket.OnError; 
import javax.websocket.OnMessage; 
import javax.websocket.OnOpen; 
import javax.websocket.Session; 
import javax.websocket.server.ServerEndpoint; 

@ServerEndpoint("/receive/fileserver") 
public class FileServer { 
    static File uploadedFile = null; 
    static String fileName = null; 
    static FileOutputStream fos = null; 
    final static String filePath="d:/download/"; 
    int fCount=0; 

    @OnOpen 
    public void open(Session session, EndpointConfig conf) { 
     System.out.println("Websocket server open"); 
    } 

    @OnMessage 
    public void processUpload(ByteBuffer msg, boolean last, Session session) { 
     System.out.println("Binary Data: " + fCount + ", Capacity: "+ msg.capacity());  
     fCount++; 
     while(msg.hasRemaining()) {   
      try { 
       fos.write(msg.get()); 
      } catch (IOException e) {    
       e.printStackTrace(); 
      } 
     }  
    } 

    @OnMessage 
    public void message(Session session, String msg) { 
     System.out.println("got msg: " + msg); 
     if(!msg.equals("end")) { 
      fileName=msg.substring(msg.indexOf(':')+1); 
      uploadedFile = new File(filePath+fileName); 
      try { 
       fos = new FileOutputStream(uploadedFile); 
      } catch (FileNotFoundException e) {  
       e.printStackTrace(); 
      } 
     }else { 
      try { 
       fos.flush(); 
       fos.close();     
      } catch (IOException e) {  
       e.printStackTrace(); 
      } 
     } 
    } 

    @OnClose 
    public void close(Session session, CloseReason reason) { 
     System.out.println("socket closed: "+ reason.getReasonPhrase()); 
    } 

    @OnError 
    public void error(Session session, Throwable t) { 
     t.printStackTrace(); 

    } 
} 

客戶:

<html> 
<head> 
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> 
<title>Chat</title> 
</head> 
<body> 
    <h2>File Upload</h2> 
    Select file 
    <input type="file" id="filename" /> 
    <br> 
    <input type="button" value="Connect" onclick="connectChatServer()" /> 
    <br> 
    <input type="button" value="Upload" onclick="sendFile()" /> 
    <script> 
     var ws; 

     function connectChatServer() { 
      ws = new WebSocket(
        "ws://localhost:8080/MyHomePage/receive/fileserver"); 

      ws.binaryType = "arraybuffer"; 
      ws.onopen = function() { 
       alert("Connected.") 
      }; 

      ws.onmessage = function(evt) { 
       alert(evt.msg); 
      }; 

      ws.onclose = function() { 
       alert("Connection is closed..."); 
      }; 
      ws.onerror = function(e) { 
       alert(e.msg); 
      } 

     } 


     function sendFile() { 
      var file = document.getElementById('filename').files[0]; 
      ws.send('filename:'+file.name); 
      var reader = new FileReader(); 
      var rawData = new ArrayBuffer();    

      var fStart = 0; //start byte 
      var fEnd = 1024*1024; //packet size & end byte when slicing file. 
      var fileFrag; //file fragment      

      reader.loadend = function() {   
       console.log('load end'); 
      } 

      reader.onload = function(e) { 
       if(e.target.readyState == FileReader.DONE) { 
        rawData = e.target.result;    
        //var blob = new Blob([rawData]);   
        ws.send(rawData); 
       }    
      } 

      fileFrag = file.slice(fStart, fEnd); 
      reader.readAsArrayBuffer(fileFrag);   

      objRun = setInterval(function() {    
       if (ws.bufferedAmount == 0) {     
        if(reader.readyState == FileReader.DONE) {      
         if(fStart<file.size) {       
          fStart = fEnd + 1; 
          fEnd = fStart + 1024*1024; 
          fileFrag = file.slice(fStart, fEnd); 
          console.log('fileFrag Size: ' + fileFrag.size + 'Frag End: ' + fEnd); 
          reader.readAsArrayBuffer(fileFrag); 
         } else clearInterval(objRun); 
        } //end of readyState 
       } //end of ws.buffer 
      }, 5);//end of setInterval  
     }//end of sendFile()  

    </script> 
</body> 
</html> 

根據服務器端日誌,零散的數據大小是8K。我怎樣才能增加這個?或者有什麼辦法來提高上傳速度?

感謝提前:)

回答

0

嘗試把setMaxBinaryMessageBufferSize()到1MB到您的會話。不完全知道javax,但使用碼頭它並沒有改變碎片大小,但速度大大提高。

0

會話對象有很多方法。其中一些被引入來處理你的問題。

setMaxBinaryMessageBufferSize(int lenght) - 因爲您的客戶似乎一次發送整個文件數據,服務器上的緩衝區無法處理該大小。

實際上,發送整個文件數據會使程序易受攻擊,並且依賴於它所處理的文件。這也不是一個好的表現決定。因爲你提到你的流程運行速度很慢。一般來說,將足夠大的緩衝區大小分配給內存中的文件數據可能會降低性能,因爲它可能導致內存交換。

我會通過多個段上傳大文件。我使用一些套接字API(而不是WebSocket API)來完成這項工作,並且工作速度非常快。

另一點。我注意到你正在使用兩種OnMessage方法來處理不同的消息類型。不過,我認爲你需要在這種情況下使用MessageHandlers,否則你的程序,如你所報告的,可能會混淆哪個消息去哪個方法。

請看這個例子 https://github.com/nickytd/websocket-message-handlers-example/blob/master/websocket.messagehandler.web/src/main/java/websocket/messagehandler/example/endpoints/FullEchoEndpoint.java

+1

我喜歡你的這個打算。在'setMaxBinaryMessageBufferSize(int lenght)'上使用反標來指示代碼,並且不僅僅提供僅鏈接的答案,而是將鏈接中最相關的代碼粘貼到答案中並解釋它們,然後包含源代碼鏈接。 – DrewT