Pb BufferedInputStream/BufferedOutputStream (pièce jointe avec JavaMail)

urikane Messages postés 16 Date d'inscription lundi 15 décembre 2003 Statut Membre Dernière intervention 24 août 2004 - 23 août 2004 à 14:22
cs_Guillaume1er Messages postés 8 Date d'inscription mardi 17 décembre 2002 Statut Membre Dernière intervention 3 juin 2006 - 4 mars 2005 à 13:45
Bonjour à tous. Voici mon problème.
Je suis en train de faire une appli qui doit télécharger les pièces jointes dans une boîte mail.
J'utilise l'API JavaMail
Voici le code de la méthode qui enregistre les pièces jointes sur le disque dur:
public boolean savePieceJointe(String rep,Part p)
{
String filename,extension="";
StringTokenizer st;
BufferedInputStream bis;
BufferedOutputStream bos;
InputStream is;
FileOutputStream fos;
File f;
int count,lu,nbtk,taille;
boolean ret=false;

try{
filename=p.getFileName();
st=new StringTokenizer(filename,".");
nbtk=st.countTokens();
for(int m=0;m<nbtk;m++){
extension=st.nextToken();
}
if((extension.equals("zip"))||(extension.equals("csv"))){
System.out.println("nom du fichier: "+filename);
f=new File(rep+"\"+filename);
is=p.getInputStream();
count=0;
taille=filename.length();
while(f.exists()){
count++;
f=new File(rep+"\"+filename.substring(0,taille-4)+"_"+count+filename.substring(taille-4,taille));
}
fos=new FileOutputStream(f);
bos=new BufferedOutputStream(fos);
bis=new BufferedInputStream(is);
try{
while((lu=bis.read())!=-1){
bos.write(lu);
System.out.print(lu);
}
}catch(IOException ioe){throw ioe;}
finally{
bos.flush();
bos.close();
bis.close();
}
}
else{
ret=true;
}
}catch(Exception e){e.printStackTrace();}
return ret;
}

Le seul moyen d'accéder à la pièce jointe est un InputStream (obtenu à partir d'un Part -> cf JavaMail)
Le problème est avec certaine pièce jointe, pas toute (en fait c'est aléatoire :sad) ) j'ai l'exception suivante:

java.io.IOException: Error in encoded stream: needed 4 valid base64 characters but only got 3 before EOF, the valid characters were: "ujB"

Dans le message d'erreur, le nombre de caractère valide n'est pas forcement 3; ça dépend desfois c'est 2 ou 1

J'ai essayé à la place de InputStream d'utiliser un FileInputStream avec les fichiers qui posaient problème (les fichiers étant sur mon déjà sur mon disque dur puisque on ne peut pas obtenir de FileInputStream à partir quand les fichiers sont encore dans la boîte mail).
En fait j'ai juste fait une copie d'un encroit à un autre de mon disque. Mais là ça marche :((((
Donc le pb semble être le InputStream mais je n'ai que ça (enfin j'ai bien regardé la javadoc de l'API JavaMail et Activation mais je n'ai rien trouvé d'autre, peut-être que j'ai mal cherché)

Si quelqu'un à une idée... en plus il faut que j'ai fini ça ce soir :(((
Please help meeeeee :sad)

ps: dsl pour le code je n'arrive pas à l'afficher clairement

21 réponses

wargre Messages postés 649 Date d'inscription mardi 8 juin 2004 Statut Membre Dernière intervention 9 septembre 2004 7
23 août 2004 à 14:54
t'es bien en multiipart?
0
urikane Messages postés 16 Date d'inscription lundi 15 décembre 2003 Statut Membre Dernière intervention 24 août 2004
23 août 2004 à 15:18
Salut wargre :)
Merci de t'intéresser à mon pb.
Voici une partie du code de la méthode qui recherche les mails dans la boîte
msg[k] est un tableau de type Message qui contient tous les messages du dossier INBOX
....
Object obj=msg[k].getContent();
if(obj instanceof Multipart){
Multipart mu=(Multipart) obj;
try{
for(int l=0;l<mu.getCount();l++){
Part pt=mu.getBodyPart(l);
String dispos=pt.getDisposition();
if(dispos!=null){
if((dispos.equalsIgnoreCase(Part.ATTACHMENT))||(dispos.equalsIgnoreCase(Part.INLINE))){
boolean tmp=savePieceJointe(fich_dl+"\"+chemin,pt);
res=res&&tmp;
lu[0]=msg[k];
}
}
}
}catch(IndexOutOfBoundsException ioobe){ioobe.printStackTrace();}
......


c'est bien multipart

au fait, tu sais comment faire apparaitre le code correctement, je vuex dire avec les indentations?

Thx
0
urikane Messages postés 16 Date d'inscription lundi 15 décembre 2003 Statut Membre Dernière intervention 24 août 2004
23 août 2004 à 18:24
:sad) plz de l'aide sinon je suis foutu
0
wargre Messages postés 649 Date d'inscription mardi 8 juin 2004 Statut Membre Dernière intervention 9 septembre 2004 7
24 août 2004 à 09:27
bas y'a pas un exemple sur le web?
0

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

Posez votre question
urikane Messages postés 16 Date d'inscription lundi 15 décembre 2003 Statut Membre Dernière intervention 24 août 2004
24 août 2004 à 10:03
Bin si y'a quelques exemples (très peu, et en anglais :()
C'est justement à partir ces exemples que écris mon code
http://www.jguru.com/faq/view.jsp?EID=26996
Pour eux, il faut juste copier les octets de l'inputstream vers le fichier sur mon disque.
Seulement ça marche pas.
En plus je viens de me rendre compte d'un truc:
même avec un fichier sur lequel ça marchait (un fichier .txt, comme ça je peux modifier la taille facilement) il reste un autre problème -> le fichier que j'ai récupéré sur mon disque dur ne fait pas la même taille que l'original :sad)
D'après ce que j'ai pu lire, lorsque qu'on attache une pièce jointe à un mail, elle est codée et ça taille entre le moment où elle est sur le disque dur et le moment où elle est attachée au mail.
Une fois qu'on veut enregistre la pièce jointe après réception du mail, elle est d'abord décodée, puis après copier sur le disque dur.

Seulement voila, dans leur exemple il ne se soucis pas de cette histoire de codage/décodage.
0
wargre Messages postés 649 Date d'inscription mardi 8 juin 2004 Statut Membre Dernière intervention 9 septembre 2004 7
24 août 2004 à 10:31
ah je savais pas que c'etait pas inclu le decodage :

utilise
import sun.misc.BASE64Decoder;

BASE64Decoder dec=new BASE64Decoder();
byte buff[]=dec.decode(p.getInputStream());

ton fichier est alors contenu dans buff

le truc etrange c'est qu'il te met une erreur d'alignement alors que tu n'a pas encore decoder bizare...
0
urikane Messages postés 16 Date d'inscription lundi 15 décembre 2003 Statut Membre Dernière intervention 24 août 2004
24 août 2004 à 11:18
Salut wargre.

J'ai essayé ton truc mais ça ne marche pas, enfin ça ne compile pas. Le compilateur a un pb avec cette ligne là:
byte buff[]=dec.decode(p.getInputStream());

=>cannot resolve symbol method decode(java.io.InputStream)

En plus la classe BASE64Decoder est pas dans la javadoc :sad)

Je viens aussi de trouver un truc dans la javadoc de l'API JavaMail pour Part (méthode getInputStream):
Return an input stream for this part's "content". Any mail-specific transfer encodings will be decoded before the input stream is provided.

Si je comprend bien ça veut dire qu'il a un décodage automatique par java avant que le flux soit retourner par getInputStream.
En tout cas, ça marche pas :((((
0
wargre Messages postés 649 Date d'inscription mardi 8 juin 2004 Statut Membre Dernière intervention 9 septembre 2004 7
24 août 2004 à 11:24
bon ben alors pas la peine de decodeur.... (au fait c'est decodeBuffer et pas decode )

fait un fichier texte contenant un texte a la con et passe le a travers le mail et dit moi ce qu'il y a dans le fichier d'entree et de sortie.
0
urikane Messages postés 16 Date d'inscription lundi 15 décembre 2003 Statut Membre Dernière intervention 24 août 2004
24 août 2004 à 11:43
Bin je sais pas si faut pas décoder?!
Et puis decodeBuffer ça prend un tableau de byte en paramètres, or moi j'ai un InputStream.
Bref j'ai tester avec ce fichier là
Microsoft ScanDisk

Fichier journal g?n?r? le 23/08/2004 ? 21:10.

Les v?rifications faites par ScanDisk sur le lecteur C ont abouti aux
    r?sultats suivantsÿ:

Arborescence des r?pertoires

         Aucun probl?me trouv? par ScanDisk.
     
Table d'allocation des fichiers

         Aucun probl?me trouv? par ScanDisk.
     
Syst?me de fichiers

         ScanDisk n'a effectu? aucun test.
     
Examen de la surface

         ScanDisk n'a effectu? aucun test.


> taille485 octets
Et le fichier téléchargé: =>463 octets

Microsoft ScanDisk

Fichier journal g?n?r? le 23/08/2004 ? 21:10.

Les v?rifications faites par ScanDisk sur le lecteur C ont abouti aux
    r?sultats suivantsÿ:

Arborescence des r?pertoires

         Aucun probl?me trouv? par ScanDisk.
     
Table d'allocation des fichiers

         Aucun probl?me trouv? par ScanDisk.
     
Syst?me de fichiers

         ScanDisk n'a effectu? aucun test.
     
Examen de la surface

         ScanDisk n'


J'ai essayé plusieurs fois le même mail pour voir s'il y avait une taille différente à chaque fois mais c'est toujours 463 octets.
0
wargre Messages postés 649 Date d'inscription mardi 8 juin 2004 Statut Membre Dernière intervention 9 septembre 2004 7
24 août 2004 à 11:55
alors la ??

essais de faire:

FileOutputStream fout=new ....
byte b[]=new byte[1024];
int l;

while ((l=is.read(b))!=0){
fout.write(b,0,l);
}

fout.close();

au lieu de prendre 1 char à la fois.
0
urikane Messages postés 16 Date d'inscription lundi 15 décembre 2003 Statut Membre Dernière intervention 24 août 2004
24 août 2004 à 12:53
Je viens d'essayer (enfin en remplaçant le test !=0 par !=-1 sinon j'ai un OutOfBoundException)

En tout cas ça change rien. => même résultat 463 octets

Chuis trop désepéré.
C'est bizarre que je trouve aucun sujet sur les forums à ce sujet
Y'a des trucs pour envoyer des pièces jointes mais pas pour les télécharger :sad)
0
wargre Messages postés 649 Date d'inscription mardi 8 juin 2004 Statut Membre Dernière intervention 9 septembre 2004 7
24 août 2004 à 13:17
alors la.....

ptet essayer de refaire le truc from scratch de facon differente (?)

j'ai aucune idee desole...
0
urikane Messages postés 16 Date d'inscription lundi 15 décembre 2003 Statut Membre Dernière intervention 24 août 2004
24 août 2004 à 13:35
ptet essayer de refaire le truc from scratch de facon differente (?)


Euh je comprend pas se que tu as voulu dire?
En tout cas merci quand même d'avoir essayé :)

Y'a aussi une classe MimeUtility dans l'API JavaMail avec une méthode encode, mais je sais pas trop si je peux utiliser sur l'InputStream vu que apparement (je dis bien apparement) le flux a été décodé avant d'être retourné par getInputStream
0
wargre Messages postés 649 Date d'inscription mardi 8 juin 2004 Statut Membre Dernière intervention 9 septembre 2004 7
24 août 2004 à 13:41
oui le flux est decode ca pas de probleme. ce que je ne comprend pas c'est le pourquoi de la taille diminuées.

from scratch = de zero
0
urikane Messages postés 16 Date d'inscription lundi 15 décembre 2003 Statut Membre Dernière intervention 24 août 2004
24 août 2004 à 14:59
Ouais bin je viens de me rendre compte d'un truc, c'est que ça merde du côté du fournisseur d'accès. (club-internet)
Pour tester mon application j'ai crée une adresse @club-internet
et j'envoie des mails depuis mon adresse (qui est aussi une adresse club-internet)

J'ai fait les tests suivants:
-envoyer un mail avec un fichier texte de 1022 octets en piece jointe depuis le site de club-internet (donc pas par outlook) et récupérer le mail par outlook

-envoyer exactement le même mail de la même manière mais cette fois le récupérer en consultant ma boîte depuis le site de club-internet et en enregistrant ensuite la pièce jointe sur mon disque dur

=> résultat dans les deux cas c'est n'importe quoi
*par outlook le fichier téléchargé est plus grand->1026 octets (en fait y'a 2 saut de ligne en plus)
*par le site il est carrement plus petit et en plus je perd une partie du formattage (saut de lignes remplacé par un carré)->976 octets

J'ai refais le même test avec un fichier .zip
En revanche là dans les deux cas je retombe sur la bonne taille

Un autre truc que comprend pas:
le message d'erreur qu'il me met montre semblerait montrer qu'il n'a pas décodé le flux puisque lorsque j'ai ce message j'ai qd même une partie du fichier (même s'il est corrompu vu qu'il n'est pas complet)
java.io.IOException: Error in encoded stream: needed 4 valid base64 characters but only got 3 before EOF, the valid characters were: "ujB"
0
wargre Messages postés 649 Date d'inscription mardi 8 juin 2004 Statut Membre Dernière intervention 9 septembre 2004 7
24 août 2004 à 15:05
Si il le decode mais le probleme c'est le dernier bloc a decoder qui n'est pas complet. J'ai l'impression que le padding n'est pas bon... (ou absent)
0
urikane Messages postés 16 Date d'inscription lundi 15 décembre 2003 Statut Membre Dernière intervention 24 août 2004
24 août 2004 à 15:51
Je suis pas sur que ce soit forcement le dernier bloc vu qu'une fois en testant avec un fichier zip de 9ko je crois, il m'en avait copier que ~2ko
Le pb c'est j'ai l'impression que java il décode (en supposant qu'il le fasse à chaque fois) avec base64.
Or je viens d'essayé d'envoyé un mail avec un zip de 9,5ko depuis le site de club-internet, puis j'ai lancé le programme et résultat:
=> toujours la même erreur
/code
java.io.IOException: Error in encoded stream: needed 4 valid base64 characters b
ut only got 3 before EOF, the valid characters were: "ujB"
at com.sun.mail.util.BASE64DecoderStream.decode(BASE64DecoderStream.java
:179)
at com.sun.mail.util.BASE64DecoderStream.read(BASE64DecoderStream.java:7
8)
at com.sun.mail.util.BASE64DecoderStream.read(BASE64DecoderStream.java:1
03)
at java.io.BufferedInputStream.fill(BufferedInputStream.java:183)
at java.io.BufferedInputStream.read(BufferedInputStream.java:201)
at Boite.savePieceJointe(Boite.java:250)
at Boite.verifier(Boite.java:193)
at Tache.verifier_boite(Tache.java:98)
at Tache.run(Tache.java:76)
/code
Seulement avant j'avais regardé dans le dossier message envoyé et le champ Content-Transfer-Encoding est à quoted-printable et pas à base64
Donc comment ça se fait qu'il me mette une erreur avec base64 alors que 'quoted-printable' est utilisé :question)
0
wargre Messages postés 649 Date d'inscription mardi 8 juin 2004 Statut Membre Dernière intervention 9 septembre 2004 7
24 août 2004 à 16:11
plus aucune idee
0
urikane Messages postés 16 Date d'inscription lundi 15 décembre 2003 Statut Membre Dernière intervention 24 août 2004
24 août 2004 à 16:28
merci quand même d'avoir cherché :)
thx @+
0
cs_Guillaume1er Messages postés 8 Date d'inscription mardi 17 décembre 2002 Statut Membre Dernière intervention 3 juin 2006
4 mars 2005 à 13:41
essaye ca :)

public class Import {


public static void main(String[] args) {
String host = "";
String username = "";
String password = "";
Properties props = new Properties();
Session session = Session.getDefaultInstance(props, null);
try{
Store store = session.getStore("imap");
store.connect(host, username, password);
Folder folder = store.getFolder("INBOX");
folder.open(Folder.READ_ONLY);
folder.expunge();
Message[] message = folder.getMessages();
for (int i=0, n=message.length; i<n; i++){
System.out.println(i + ": " + message[i].getFrom()[0] + "\t" + message[i].getSubject());
Object contenuMessage = message[i].getContent();
String typeContenu = message[i].getContentType();
if(typeContenu.indexOf("multipart")==0){
MimeMultipart mmp = (MimeMultipart)contenuMessage;
int cpt = mmp.getCount();
for(int j=0;j<cpt;j++){
MimeBodyPart mbp = (MimeBodyPart)mmp.getBodyPart(j);
typeContenu = mbp.getContentType();
if(typeContenu.indexOf("TEXT")!=0){
String nomfichier = mbp.getFileName();
Object fichier = mbp.getContent();
InputStream is = mbp.getInputStream();
sauveFichier(fichier,nomfichier,is);
}
}
}else if(typeContenu.indexOf("TEXT")!=0){
String nomfichier = message[i].getFileName();
InputStream is = message[i].getInputStream();
sauveFichier(contenuMessage,nomfichier,is);
}
}
folder.close(false);
store.close();
}catch(Exception e){e.printStackTrace();}
}

public static void sauveFichier(Object fichier, String nom, InputStream is) throws IOException{
if (fichier instanceof BASE64DecoderStream){
FileOutputStream fos = new FileOutputStream("D:/" + nom);
BufferedOutputStream bos = new BufferedOutputStream(fos);
BufferedInputStream bis = new BufferedInputStream(is);
int aByte;
while ((aByte = bis.read()) != -1) {
bos.write(aByte);
}
bos.flush();
bos.close();
bis.close();
}
}
}

si ca peut aider
0
Rejoignez-nous