使用 java websocket API 和 Javascript 上传文件

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/21769470/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 10:33:34  来源:igfitidea点击:

File upload using java websocket API and Javascript

javajavascriptwebsocketblob

提问by parn

I'm studying websocket and have done chat program with websocket/json. But I'm stuck at file uploading ATM. Any advice & answer would be thankful.

我正在学习 websocket 并且已经使用 websocket/json 完成了聊天程序。但我被困在文件上传 ATM 上。任何建议和答案将不胜感激。

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? Then how?

Q2:我应该将数据类型更改为 Blob 以在 javascript 端传输文件吗?那怎么办?

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

谢谢阅读 :)

回答by parn

After some researches and tries, I found out that 'reader.readAsBinaryString(file);' was a cause of Question 1. Changing it into 'reader.readAsArrayBuffer(file);' my first problem has been solved.

经过一些研究和尝试,我发现'reader.readAsBinaryString(file);' 是问题 1 的原因。将其更改为 'reader.readAsArrayBuffer(file);' 我的第一个问题已经解决了。

In addition, since websocket transfers a file as several partial data automatically, I changed source as below. This works!only when the file size is not so big. :/

另外,由于 websocket 自动将文件传输为多个部分数据,因此我将源更改如下。这有效!仅当文件大小不是那么大时。:/

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?

我仍然不知道如何传输更大的文件。(我怀疑自动超时和/或缓冲区大小)。有什么建议吗?

回答by Konga Raju

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

You can through this articleto get an idea about the complete work flow, its working with Websocket.

您可以通过本文了解完整的工作流程,以及它与 Websocket 的协同工作。