简体   繁体   English

使用Java Websocket API和Javascript上传文件

[英]File upload using java websocket API and Javascript

I'm studying websocket and have done chat program with websocket/json. 我正在研究websocket,并已使用websocket / json完成了聊天程序。 But I'm stuck at file uploading ATM. 但是我被卡在文件上传ATM上。 Any advice & answer would be thankful. 任何建议和答案将是感激的。

Server side: 服务器端:

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 {
    @OnOpen
    public void open(Session session, EndpointConfig conf) {
        System.out.println("chat ws server open");
    }

    @OnMessage
    public void processUpload(ByteBuffer msg, boolean last, Session session) {
        System.out.println("Binary message");

        FileOutputStream fos = null;
        File file = new File("D:/download/tmp.txt");
        try {
            fos = new FileOutputStream(file);
        } catch (FileNotFoundException e) {         
            e.printStackTrace();
        }

        byte readdata = (byte) -999;
        while(readdata!=-1) {
            readdata=msg.get();
            try {
                fos.write(readdata);
            } catch (IOException e) {               
                e.printStackTrace();
            }
        }

    }

    @OnMessage
    public void message(Session session, String msg) {
        System.out.println("got msg: " + msg + msg.length());

    }

    @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>
<script type="text/javascript" src="/MyHomePage/jquery-2.0.3.min.js"></script>
</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];
            var reader = new FileReader();
            var rawData = new ArrayBuffer();            

            reader.loadend = function() {

            }
            reader.onload = function(e) {
                rawData = e.target.result;
                ws.send(rawData);
                alert("the File has been transferred.")
            }

            reader.readAsBinaryString(file);

        }


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

server side closed reason message is as below 服务器端关闭原因消息如下

socket closed: The decoded text message was too big for the output buffer and the endpoint does not support partial messages 套接字已关闭:解码的文本消息对于输出缓冲区而言太大,并且端点不支持部分消息

Q1: It seems that it is finding text processing method instead of binary processing method according to the closed reason, how can I fix this? Q1:似乎是根据封闭的原因找到文本处理方法而不是二进制处理方法,我该如何解决?

Q2: Should I change data type to Blob to transfer file on javascript side? Q2:是否应该将数据类型更改为Blob以在javascript端传输文件? Then how? 那怎么办

extra Q: May anyone link example source(es) of websocket file transferring(java websocket or javascript either/both)? 额外的问题:有人可以链接示例Websocket文件传输的源(java websocket或javascript双向)吗?

Thanks for reading :) 谢谢阅读 :)

After some researches and tries, I found out that 'reader.readAsBinaryString(file);' 经过一些研究和尝试,我发现“ reader.readAsBinaryString(file);” was a cause of Question 1. Changing it into 'reader.readAsArrayBuffer(file);' 是引起问题1的原因。将其更改为“ reader.readAsArrayBuffer(file);” my first problem has been solved. 我的第一个问题已经解决。

In addition, since websocket transfers a file as several partial data automatically, I changed source as below. 另外,由于websocket会自动将文件作为多个部分数据传输,因此我将源更改如下。 This works! 这可行! only when the file size is not so big. 仅当文件大小不太大时。 :/ :/

Changed server side source: 更改服务器端源:

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/";

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

    @OnMessage
    public void processUpload(ByteBuffer msg, boolean last, Session session) {
        System.out.println("Binary Data");      

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

    }
}

Browser(Client) side: 浏览器(客户端):

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Chat</title>
<script type="text/javascript" src="/MyHomePage/jquery-2.0.3.min.js"></script>
</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();            
            //alert(file.name);

            reader.loadend = function() {

            }
            reader.onload = function(e) {
                rawData = e.target.result;
                ws.send(rawData);
                alert("the File has been transferred.")
                ws.send('end');
            }

            reader.readAsArrayBuffer(file);

        }


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

Still I cannot figure out how to transfer larger size file . 我仍然不知道如何传输更大尺寸的文件 (I'm suspecting auto-timeout and/or buffer size). (我怀疑是自动超时和/或缓冲区大小)。 Any advice plz? 有什么建议吗?

In My case its working to upload large files without any browser crash or socket close. 就我而言,它可以上传大文件而不会导致浏览器崩溃或套接字关闭。

Please follow the following steps to work it. 请按照以下步骤进行操作。

  1. Use web workers to slice the large files 使用网络工作者对大文件进行切片
  2. send the chunks to server using Websocket from main thread 使用Websocket从主线程将块发送到服务器
  3. construct file on server side based on blob or chunk information. 根据Blob或块信息在服务器端构造文件。
  4. maintain unique id for each file while uploading files to server so that server can recognize to which file append 在将文件上传到服务器时,为每个文件维护唯一的ID,以便服务器可以识别附加到哪个文件
  5. In server side initially place it in temp folder with unique id after completion move it to the exact folder. 在服务器端,最初将其放置在具有唯一ID的temp文件夹中,完成后将其移动到确切的文件夹中。

You can through this article to get an idea about the complete work flow, its working with Websocket. 您可以通过本文获得有关完整工作流程及其与Websocket一起使用的想法。

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

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