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 :)
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.
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