Envoie de fichier [Résolu]

lossehelin 51 Messages postés jeudi 10 mai 2012Date d'inscription 5 juillet 2012 Dernière intervention - 27 juin 2012 à 09:07 - Dernière réponse : Twinuts 5282 Messages postés dimanche 4 mai 2003Date d'inscription 19 octobre 2018 Dernière intervention
- 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)
Afficher la suite 

Votre réponse

19 réponses

Meilleure réponse
Twinuts 5282 Messages postés dimanche 4 mai 2003Date d'inscription 19 octobre 2018 Dernière intervention - 28 juin 2012 à 22:16
3
Merci
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

Merci Twinuts 3

Avec quelques mots c'est encore mieux Ajouter un commentaire

Codes Sources a aidé 93 internautes ce mois-ci

Commenter la réponse de Twinuts
Meilleure réponse
Twinuts 5282 Messages postés dimanche 4 mai 2003Date d'inscription 19 octobre 2018 Dernière intervention - 29 juin 2012 à 09:50
3
Merci
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

Merci Twinuts 3

Avec quelques mots c'est encore mieux Ajouter un commentaire

Codes Sources a aidé 93 internautes ce mois-ci

Commenter la réponse de Twinuts
cormandyr 600 Messages postés samedi 20 mai 2006Date d'inscription 8 juillet 2016 Dernière intervention - 27 juin 2012 à 10:23
0
Merci
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é...
Commenter la réponse de cormandyr
lossehelin 51 Messages postés jeudi 10 mai 2012Date d'inscription 5 juillet 2012 Dernière intervention - 27 juin 2012 à 10:51
0
Merci
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 !
Commenter la réponse de lossehelin
cs_Julien39 6450 Messages postés mardi 8 mars 2005Date d'inscription 17 mai 2018 Dernière intervention - 27 juin 2012 à 10:58
0
Merci
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 ?
Commenter la réponse de cs_Julien39
cormandyr 600 Messages postés samedi 20 mai 2006Date d'inscription 8 juillet 2016 Dernière intervention - 27 juin 2012 à 11:06
0
Merci
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...
Commenter la réponse de cormandyr
lossehelin 51 Messages postés jeudi 10 mai 2012Date d'inscription 5 juillet 2012 Dernière intervention - 27 juin 2012 à 11:26
0
Merci
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
Commenter la réponse de lossehelin
Twinuts 5282 Messages postés dimanche 4 mai 2003Date d'inscription 19 octobre 2018 Dernière intervention - 27 juin 2012 à 21:44
0
Merci
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
Commenter la réponse de Twinuts
lossehelin 51 Messages postés jeudi 10 mai 2012Date d'inscription 5 juillet 2012 Dernière intervention - 28 juin 2012 à 09:02
0
Merci
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 ...
Commenter la réponse de lossehelin
Twinuts 5282 Messages postés dimanche 4 mai 2003Date d'inscription 19 octobre 2018 Dernière intervention - 28 juin 2012 à 09:14
0
Merci
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
Commenter la réponse de Twinuts
lossehelin 51 Messages postés jeudi 10 mai 2012Date d'inscription 5 juillet 2012 Dernière intervention - 28 juin 2012 à 09:28
0
Merci
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 ?
Commenter la réponse de lossehelin
lossehelin 51 Messages postés jeudi 10 mai 2012Date d'inscription 5 juillet 2012 Dernière intervention - 28 juin 2012 à 14:47
0
Merci
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
Commenter la réponse de lossehelin
lossehelin 51 Messages postés jeudi 10 mai 2012Date d'inscription 5 juillet 2012 Dernière intervention - 29 juin 2012 à 08:44
0
Merci
Bonjour, et bien merci, j'vais essayer votre code, et je vous dirai si cela fonctionne mieux :)
Commenter la réponse de lossehelin
lossehelin 51 Messages postés jeudi 10 mai 2012Date d'inscription 5 juillet 2012 Dernière intervention - 29 juin 2012 à 08:59
0
Merci
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 !
Commenter la réponse de lossehelin
lossehelin 51 Messages postés jeudi 10 mai 2012Date d'inscription 5 juillet 2012 Dernière intervention - 29 juin 2012 à 09:35
0
Merci
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));
Commenter la réponse de lossehelin
lossehelin 51 Messages postés jeudi 10 mai 2012Date d'inscription 5 juillet 2012 Dernière intervention - 29 juin 2012 à 10:11
0
Merci
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 :/
Commenter la réponse de lossehelin
Twinuts 5282 Messages postés dimanche 4 mai 2003Date d'inscription 19 octobre 2018 Dernière intervention - 29 juin 2012 à 10:18
0
Merci
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
Commenter la réponse de Twinuts
lossehelin 51 Messages postés jeudi 10 mai 2012Date d'inscription 5 juillet 2012 Dernière intervention - 29 juin 2012 à 10:27
0
Merci
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 :)
Commenter la réponse de lossehelin
Twinuts 5282 Messages postés dimanche 4 mai 2003Date d'inscription 19 octobre 2018 Dernière intervention - 29 juin 2012 à 10:39
0
Merci
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
Commenter la réponse de Twinuts

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.