简体   繁体   English

Websocket文件上传速度问题(Java websocket API和Javascript)

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

I barely made websocket file upload function. 我几乎没有做过websocket文件上传功能。 But uploading speed seems to be slow. 但上传速度似乎很慢。 I have used Java API for websocket Server and javascript for client. 我已经使用Java API for websocket Server和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. 根据服务器端日志,碎片数据大小为8K。 How can I increase this? 我怎么能增加这个? or is there any way to improve uploading speed? 或者有什么方法可以提高上传速度吗?

Thanks in advance :) 提前致谢 :)

Try to put setMaxBinaryMessageBufferSize() to 1MB to your session. 尝试将setMaxBinaryMessageBufferSize()置于1MB到您的会话。 Don't know exactly with javax but with jetty it does not changed the fragments size but the speed is increased enormously. 不完全知道javax,但是使用jetty它不会改变碎片大小,但速度会大大增加。

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. setMaxBinaryMessageBufferSize(int lenght) - 因为您的客户端似乎立即发送整个文件数据,服务器上的缓冲区无法处理该大小。

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. 我使用一些套接字API(而不是WebSocket API)来做到这一点,它的工作速度非常快。

Another point. 还有一点。 I noticed that you are using two OnMessage methods for different message types. 我注意到您正在为不同的消息类型使用两种OnMessage方法。 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. 但是,我认为你需要在那种情况下使用MessageHandlers,否则你报告的程序会混淆哪个消息去哪个方法。

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://github.com/nickytd/websocket-message-handlers-example/blob/master/websocket.messagehandler.web/src/main/java/websocket/messagehandler/example/endpoints/FullEchoEndpoint.java

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM