Websocket File upload speed issue (Java websocket API and Javascript)

隐身守侯 提交于 2020-01-01 16:58:27

问题


I barely made websocket file upload function. But uploading speed seems to be slow. I have used Java API for websocket Server and javascript for client.

Server:

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();

    }
}

Client:

<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>

According to server side log, fragmented data size is 8K. How can I increase this? or is there any way to improve uploading speed?

Thanks in advance :)


回答1:


Try to put setMaxBinaryMessageBufferSize() to 1MB to your session. Don't know exactly with javax but with jetty it does not changed the fragments size but the speed is increased enormously.




回答2:


The session object has many methods. Some of them are introduced to deal with your problem.

setMaxBinaryMessageBufferSize(int lenght) - because it seems that your client sends the entire file data at once, the the buffer on the server is unable to handle that size.

In reality, sending the whole file data makes the program vulnerable and dependent on the file it processes. It is also not a good performance decision. Because you mention that your process works quite slow. I general, allocating the buffer size large enough to be able to hold the file data in memory could degrade performance because it could cause memory swapping.

I would upload large files by multiple segments. I did this using some socket APIs (not WebSocket API) and it work quite fast.

Another point. I noticed that you are using two OnMessage methods for different message types. However, I think you need to use in that case MessageHandlers, otherwise your program, as you reported, can confuse which message go to which method.

Please see this example https://github.com/nickytd/websocket-message-handlers-example/blob/master/websocket.messagehandler.web/src/main/java/websocket/messagehandler/example/endpoints/FullEchoEndpoint.java



来源:https://stackoverflow.com/questions/21846530/websocket-file-upload-speed-issue-java-websocket-api-and-javascript

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!