Envoie de fichier

Résolu
lossehelin Messages postés 51 Date d'inscription jeudi 10 mai 2012 Statut Membre Dernière intervention 5 juillet 2012 - 27 juin 2012 à 09:07
Twinuts Messages postés 5374 Date d'inscription dimanche 4 mai 2003 Statut Modérateur Dernière intervention 3 mars 2023 - 29 juin 2012 à 10:39
Bonjour :) !

Avant de partir en vacances (être étudiant, c'est tellement bien), j'aimerai un peu approfondir mes connaissances en Java (si je peux dire ça, je dirai plutôt, élargir, alimenter).

J'ai voulu coder quelque chose d'utile pour une fois, je suis donc parti d'un problème que j'ai souvent:
Lorsque je veux partager un fichier avec quelqu'un, quelle que soit sa nature, je dois passer soit par mon serveur FTP, soit par un hébergeur quelconque, ce qui m'embête, c'est que du coup, ça génère deux actions, je dois uploader le fichier, et le quelqu'un a qui il est destiné, doit ensuite le retélécharger.

Mon idée était donc de coder un applet web permettant à deux personnes de s'envoyer directement des fichiers !

J'ai donc étudié un peu les sockets, et codé un mini chat en mode console pour vérifier que j'avais bien tout compris.
Seulement, je peux transférer du texte, mais je n'ai aucune idée de comment cela fonctionne avec des fichiers !

Je me demandais aussi, si un Applet permet ce genre de transfert, même signé ?

Merci d'avance, et bonne journée :).

(peut-être que ce que je cherche à faire existe déjà, mais, ça n'empêchera pas que j'ai envie de le faire par moi-même)

19 réponses

Twinuts Messages postés 5374 Date d'inscription dimanche 4 mai 2003 Statut Modérateur Dernière intervention 3 mars 2023 111
28 juin 2012 à 22:16
Salut,

Ok ok, bon ici je n'utilise pas de client serveur mais bon comme j'utilise les flux InputStream/OutputStream leurs provenance importe peu.

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;

public class StreamCopy {
  
  private static final int BUFFER_SIZE = 1024;
  
  public static void main(final String[] args) throws Throwable {
    InputStream is = new FileInputStream("movie.mp4"); /* 245,084 Mo chez moi */
    OutputStream os = new FileOutputStream("movie2.mp4");
    copy(is, os, true);
    
    is = new FileInputStream("doc.odt"); /* 14 Ko chez moi */
    os = new FileOutputStream("doc2.odt");
    copy(is, os, true);
  }
  
  public static void copy(final InputStream is, final OutputStream os, boolean closeInput) throws Throwable {
    final BufferedInputStream bis = new BufferedInputStream(is);
    final BufferedOutputStream bos = new BufferedOutputStream(os);
    int i, size = 0;
    final byte buffer[] = new byte[BUFFER_SIZE];
    while ((i = bis.available()) > 0) {
      size = i > BUFFER_SIZE ? BUFFER_SIZE : i;
      is.read(buffer, 0, size);
      bos.write(buffer, 0, size);
    }
    bos.close(); /* doit être fermé */
    if(closeInput) bis.close();
  }
}



Note: Pour rappel si tu fermes l'InputStream tu fermes le socket du client, après c'est peut-être voulu.


-----

"On n'est pas au resto : ici on ne fait pas dans les plats tout cuits ..."

OoWORAoO
3
Twinuts Messages postés 5374 Date d'inscription dimanche 4 mai 2003 Statut Modérateur Dernière intervention 3 mars 2023 111
29 juin 2012 à 09:50
Salut,

Ok, dans ce cas ne ferme pas les fd dans la fonction transfert2.
Dsl je n'ai pas précisé dans mon ancien post mais la fermeture du flux dépend du sens.
Si je reçois un fichier via le réseau, InputStream correspond au Socket de l’émetteur du fichier et OutputStream au fichier que j'écris
Si j'envois un fichier via le réseau, InputStream au fichier et OutputStream au Socket.

Enfin j’espère que tu vois ou je veux en venir.


-----

"On n'est pas au resto : ici on ne fait pas dans les plats tout cuits ..."

OoWORAoO
3
cormandyr Messages postés 600 Date d'inscription samedi 20 mai 2006 Statut Membre Dernière intervention 8 juillet 2016 12
27 juin 2012 à 10:23
salut,

j'avoue que je ne sais pas si un applet peut le faire ou pas...
cependant, si tu veux que ton applet ait accès à ton disque dur, pour l'explorer ou utiliser un composant tel que le JFileChooser par exemple tu dois obligatoirement signer ton applet... question de sécurité...
0
lossehelin Messages postés 51 Date d'inscription jeudi 10 mai 2012 Statut Membre Dernière intervention 5 juillet 2012
27 juin 2012 à 10:51
Oui, du coup, je vais penser à la signer !

Dans le pire des cas si ça ne fonctionne pas avec un applet, je transformer mon JApplet en JPanel et j'me débrouille comme ça, mais c'est tout de suite moins accessible, chaque personne devrait télécharger mon fichier avant de pouvoir faire ça, sous forme d'applet sur une page web, c'est tout de suite beaucoup plus simple !
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
cs_Julien39 Messages postés 6414 Date d'inscription mardi 8 mars 2005 Statut Modérateur Dernière intervention 29 juillet 2020 369
27 juin 2012 à 10:58
Salut,

Niveau fonctionnement, JApplet ou JPanel, c'est la même chose. Dans tout les cas, tout est exécuté coté client.

Et dans tous les cas, tu es obligé d'utiliser un serveur central par lequel transitent les données donc, je ne suis pas certain que le mécanisme que tu décris soit envisageable. Du moins pas dans cette architecture.

Je pense que ce que tu veux faire s'approche du P2P non ?
0
cormandyr Messages postés 600 Date d'inscription samedi 20 mai 2006 Statut Membre Dernière intervention 8 juillet 2016 12
27 juin 2012 à 11:06
ou alors un échange de données dans le meme style que ce que tu peux avoir avec les logiciels de chat ou autre...
tu discute avec qqn et tu envoies un fichier...
0
lossehelin Messages postés 51 Date d'inscription jeudi 10 mai 2012 Statut Membre Dernière intervention 5 juillet 2012
27 juin 2012 à 11:26
Je note, pour les JApplet et JPanel, je pensais juste que malgré le fait qu'on signe un JApplet, certaine fonctionnalités pouvaient ne pas fonctionner !

Et sinon, je ne compte pas passer par un serveur intermédiaire, je veux vraiment que le fichier transite directement de A vers B, donc oui, ça s'approche plutôt du P2P
0
Twinuts Messages postés 5374 Date d'inscription dimanche 4 mai 2003 Statut Modérateur Dernière intervention 3 mars 2023 111
27 juin 2012 à 21:44
Salut,

Passer par un serveur intermédiaire:
Au moins pour y stocker l'applet et avoir une ip/nom de domaine fixe permettant de simplifier les mises en relation des clients (une des bases des serveurs p2p). Naturellement ce cas n'impose pas d'uploader les fichiers sur le serveur, tu peux toujours transférer les données de point à point.
Tu t'affranchis des clients qui n'ont pas d'ip fixe.
Une unique mise à jour de l'applet nécessaire.
Tu dois te procurer un serveur.
Tu dois faire du code coté serveur.
...

Passer de point à point sans passer par un serveur intermédiaire:
Est chiant si l'un des deux n'a pas d'ip fixe (si si ça peux être hyper chiant ô_O).
En cas de mise à jour tu dois mettre tout le monde à jour...
Ne nécessite pas de dépense de serveur ni de code.
...

Dans les deux cas (ici une question de point de vue) je te conseil :
D'utiliser des sockets SSL.
De supporter les reprises auto de téléchargement.
De supporter une limitation de la bande passante en download et en upload.
De bien bien réfléchir au protocole de transfert que tu veux utiliser (dispo*, proprio évolué, proprio fait à l'arrache)
...

*exemple de dispo: HTTP, FTP, SCP, etc...
Pro messagerie supportant les dl de fichier XMMP

-----

"On n'est pas au resto : ici on ne fait pas dans les plats tout cuits ..."

OoWORAoO
0
lossehelin Messages postés 51 Date d'inscription jeudi 10 mai 2012 Statut Membre Dernière intervention 5 juillet 2012
28 juin 2012 à 09:02
J'vais regarder pour les sockets SSL :).

Sinon, pour l'envoie de fichier, j'ai cru comprendre qu'il suffisait de lire avec un InputStream un fichier, le balancer dans l'OutputStream du socket, et de l'autre coté, on lit l'InputStream du socket, et on écrit le fichier avec un OutputStream sur le disque ?

Ce serait aussi "simple" que ça ?
Je me doute qu'il y a des détails encore à régler (utilisation d'un buffer etc), mais sur le principe, c'est ça ?

J'avais du faire ça en C à l'IUT, et n'étant pas très doué en C, cela m'avait paru vraiment très très compliqué, tellement que j'avais laissé cette partie là à mes camarades ...
0
Twinuts Messages postés 5374 Date d'inscription dimanche 4 mai 2003 Statut Modérateur Dernière intervention 3 mars 2023 111
28 juin 2012 à 09:14
Salut,

Oui, sur le principe même du transfert de fichier c'est aussi simple que ça, bien que tu peux avoir besoin d'encapsuler les datas dans un protocole si tu en utilises un (souvent nécessaire) mais ça reste un détail.

En C même si il n'y a pas d'OutputStream ni même d'InputStream ça reste sur le même principe.


-----

"On n'est pas au resto : ici on ne fait pas dans les plats tout cuits ..."

OoWORAoO
0
lossehelin Messages postés 51 Date d'inscription jeudi 10 mai 2012 Statut Membre Dernière intervention 5 juillet 2012
28 juin 2012 à 09:28
Je dois avouer qu'en C, j'avais pas vraiment cherché à comprendre :/.

Peux-tu m'expliquer l'encapsulage des données ?
Ou m'orienter vers un tutoriel à propos de ça ?
0
lossehelin Messages postés 51 Date d'inscription jeudi 10 mai 2012 Statut Membre Dernière intervention 5 juillet 2012
28 juin 2012 à 14:47
Je réussi plus ou moins à transférer mes fichiers (j'ai choisi des sockets simples pour l'instant), cependant, je n'ai réussi avec aucun fichier dont la taille est supérieur à 10Mo, et il arrive que même pour des fichiers plus petits, ça ne fonctionne pas ...

Je vous mets ici le code que j'ai écrit:
    /**
     * Cette méthode permet d'effectuer le transfert d'un fichier
     * @param in Le flux d'entrée du fichier
     * @param out Le flux de sortie du fichier
     * @param closeOnExit Indique s'il faut fermer les flux à la fin
     */
    public static void transfert(InputStream in, OutputStream out, boolean closeOnExit, JProgressBar jbp, long length)
    {
        try
        {
            byte[] buffer = new byte[1024];
            
            int n;
            int value = 0;
            long compteur = 0L;
            
            while( ( n = in.read(buffer) ) != -1 )
            {
                out.write(buffer, 0, n);
                out.flush();
                compteur += 1024;
                int newVal = (int) (compteur * 100 / length);
                if( newVal > value )
                {
                    value = newVal;
                    jbp.setValue(value);
                }
            }//while( ( n = in.read(buffer) ) != -1 )
        }//try
        catch (IOException ex)
        {
            JOptionPane.showMessageDialog(null, "Une erreur s'est produite pendant le transfert du fichier !\n" + ex.getMessage(), "Oups !", JOptionPane.WARNING_MESSAGE);
        }//catch (IOException ex)
        if( closeOnExit )
        {
            try
            {
                in.close();
                out.close();
            }//try
            catch (IOException owned)
            {}//catch (IOException owned)
        }//if( closeOnExit )
    }//public static void transfert(InputStream in, OutputStream out, boolean closeOnExit)


La JProgressBar que je passe en paramètre, c'est juste pour l'affichage de la progression du transfert, et la variable length, la longueur du fichier en octets (que celui qui envoie le fichier envoie d'abord à celui qui le reçoit).

J'appelle la même fonction des deux cotès, l'un avec:
transfert(new FileInputStream(fichier), socket.getOutputStream(), true);


et l'autre avec:
transfert(socket.getInputStream(), new FileOutputStream(fichier), true);


Si vous pouviez m'aider un peu, ça m'arrangerait :X
0
lossehelin Messages postés 51 Date d'inscription jeudi 10 mai 2012 Statut Membre Dernière intervention 5 juillet 2012
29 juin 2012 à 08:44
Bonjour, et bien merci, j'vais essayer votre code, et je vous dirai si cela fonctionne mieux :)
0
lossehelin Messages postés 51 Date d'inscription jeudi 10 mai 2012 Statut Membre Dernière intervention 5 juillet 2012
29 juin 2012 à 08:59
Bon et bien en local ça fonctionne bien, je dois avoir un problème quelque part dans mes sockets, j'vais regarder à nouveau tout ça !
0
lossehelin Messages postés 51 Date d'inscription jeudi 10 mai 2012 Statut Membre Dernière intervention 5 juillet 2012
29 juin 2012 à 09:35
L'erreur:
29 juin 2012 09:29:46 socketon.SockeTools transfert2
GRAVE: null
java.net.SocketException: Software caused connection abort: socket write error
at java.net.SocketOutputStream.socketWrite0(Native Method)
at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:92)
at java.net.SocketOutputStream.write(SocketOutputStream.java:136)
at java.io.BufferedOutputStream.flushBuffer(BufferedOutputStream.java:65)
at java.io.BufferedOutputStream.write(BufferedOutputStream.java:109)
at socketon.SockeTools.transfert2(SockeTools.java:121)
at socketon.TransKeton.run(TransKeton.java:75)

    public static void transfert2(InputStream in, OutputStream out, boolean closeOnExit, JProgressBar jbp, long length)
    {
        final BufferedInputStream bis = new BufferedInputStream(in);
        final BufferedOutputStream bos = new BufferedOutputStream(out);
        int i, size = 0;
        final byte buffer[] = new byte[BUFFER_SIZE];
        try
        {
            while( ( i = bis.available() ) > 0 )
            {
                size = i > BUFFER_SIZE ? BUFFER_SIZE : i;
                bis.read(buffer, 0, size);
                bos.write(buffer, 0, size);
            }
            bos.close(); //Cela correspond à cette ligne
            if( closeOnExit )
            {
                bis.close();
            }
        }
        catch (IOException ex)
        {
            Logger.getLogger(SockeTools.class.getName()).log(Level.SEVERE, null, ex);
        }
    }


Et j'appelle la méthode de cette manière:

                    FileInputStream fis = new FileInputStream(this.socketon.getFile());
                    SockeTools.transfert2(fis, this.socket.getOutputStream(), true, this.socketon.getJPB(), lengths.get(i));
0
lossehelin Messages postés 51 Date d'inscription jeudi 10 mai 2012 Statut Membre Dernière intervention 5 juillet 2012
29 juin 2012 à 10:11
Toujours pas :/

Je me suis mis un println pour vérifier qu'il crée correctement le socket dans mon client, et il le fait:
Client : connexion établie avec Socket[addr=/127.0.0.1,port=6969,localport=50019]

(et coté serveur, le socket est crée correctement aussi)

Mais j'ai toujours cette erreur:

29 juin 2012 10:08:53 socketon.SockeTools transfert2
GRAVE: null
java.net.SocketException: Software caused connection abort: socket write error
at java.net.SocketOutputStream.socketWrite0(Native Method)
at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:92)
at java.net.SocketOutputStream.write(SocketOutputStream.java:136)
at java.io.BufferedOutputStream.flushBuffer(BufferedOutputStream.java:65)
at java.io.BufferedOutputStream.write(BufferedOutputStream.java:109)
at socketon.SockeTools.transfert2(SockeTools.java:121)
at socketon.TransKeton.run(TransKeton.java:78)

Pourtant, je ferme mon input et mon output en dehors de ma fonction :/
0
Twinuts Messages postés 5374 Date d'inscription dimanche 4 mai 2003 Statut Modérateur Dernière intervention 3 mars 2023 111
29 juin 2012 à 10:18
Salut,

Le plus simple serait que tu me donnes accès au code que je puisse voir ce qui cloche (ce n'est pas forcément la méthode transfert.
Par contre je ne pourrais pas forcément me pencher dessus avant ce soir voir ce weekend.


-----

"On n'est pas au resto : ici on ne fait pas dans les plats tout cuits ..."

OoWORAoO
0
lossehelin Messages postés 51 Date d'inscription jeudi 10 mai 2012 Statut Membre Dernière intervention 5 juillet 2012
29 juin 2012 à 10:27
Bah, disons que mon code est légèrement bordélique, mais je crois avoir résolu le problème pour le transfert, la seul différence entre ma boucle qui marchait pour écrire des petites fichiers, et la votre, c'était la variable "size" qu'on envoie à la méthode write ("n" chez moi), j'ai donc modifié ça, et, ça semble fonctionner, j'ai réussi à transférer un fichier de 2Go !

Bon par contre, ça plante complètement mon interface graphique alors que je lance le transfert dans un Thread, mais, ça je nage moins que pour les sockets, alors je devrai réussir à me débrouiller ! :)

Merci pour votre aide :)
0
Twinuts Messages postés 5374 Date d'inscription dimanche 4 mai 2003 Statut Modérateur Dernière intervention 3 mars 2023 111
29 juin 2012 à 10:39
Salut,

Pour ça tu peux voir du coté de SwingWorker & Co

-----

"On n'est pas au resto : ici on ne fait pas dans les plats tout cuits ..."

OoWORAoO
0