web-dev-qa-db-fra.com

Téléchargement de fichier à l'aide de l'API Java Websocket et de Javascript

J'étudie Websocket et ai fait un programme de chat avec websocket/json. Mais je suis bloqué au téléchargement de fichiers ATM. Tout conseil et réponse seraient reconnaissants.

Du côté serveur:

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>

le message de raison fermé côté serveur est comme ci-dessous

socket fermé: le message texte décodé était trop volumineux pour le tampon de sortie et le noeud final ne prend pas en charge les messages partiels

Q1: Il semble qu’il trouve une méthode de traitement de texte au lieu d’une méthode de traitement binaire en fonction de la raison fermée, comment puis-je résoudre ce problème?

Q2: Devrais-je changer le type de données en Blob pour transférer le fichier côté javascript? Alors comment?

extra Q: Quelqu'un peut-il créer un lien vers des exemples de source (s) de transfert de fichier Websocket (Java Websocket ou javascript soit/les deux)? 

Merci d'avoir lu :)

10
parn

Après quelques recherches et essais, j'ai découvert que 'reader.readAsBinaryString (file);' était une cause de la question 1. Le changer en 'reader.readAsArrayBuffer (file);' mon premier problème a été résolu.

De plus, depuis que websocket transfère automatiquement un fichier sous forme de plusieurs données partielles, j'ai changé de source comme ci-dessous. Cela marche! uniquement lorsque la taille du fichier n'est pas si grande. :/

Source côté serveur modifiée:

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

    }
}

Côté navigateur (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];
            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>

Je n'arrive toujours pas à comprendre comment transférer un fichier de plus grande taille . (Je soupçonne un délai d'attente automatique et/ou la taille de la mémoire tampon). Un conseil plz?

3
parn

Dans mon cas, il fonctionne pour télécharger de gros fichiers sans plantage du navigateur ou fermeture du socket.

Veuillez suivre les étapes suivantes pour le faire fonctionner.

  1. Utilisez les travailleurs Web pour découper les gros fichiers
  2. envoyer les morceaux au serveur en utilisant Websocket à partir du thread principal
  3. construire le fichier côté serveur basé sur les informations blob ou chunk.
  4. conserve un identifiant unique pour chaque fichier lors du téléchargement de fichiers sur le serveur afin que celui-ci puisse reconnaître le fichier auquel le fichier doit être ajouté
  5. Au niveau du serveur, placez-le initialement dans le dossier temporaire avec un identifiant unique à la fin, déplacez-le dans le dossier exact.

Vous pouvez utiliser cet article pour vous faire une idée du flux de travail complet, de son utilisation avec Websocket.

0
Konga Raju