View Full Version : [Java] Problema sending files
Ciao ragazzi , sono sempre il tipo che deve fare il client FTP utilizzando la socket , sono a questo punto :
- uso una connessione passiva
- ho parsato il pasv
- a questo punto mi sono inchiodato al momento dell'invio dei files, ovvero:
Socket s2 = new Socket (server,finalport);
// Definisco gli stream per invio sulla nuova Socket
BufferedInputStream input = new BufferedInputStream(s2.getInputStream());
output = new BufferedOutputStream(new FileOutputStream(filename));
//
// Setto i parametri per l'upload
final int BUFFER_SIZE = 4096;
byte[] buffer = new byte;
int countlen=0;
int len = 0;
//
//Parte l'upload
int f=0;
while ((len = input.read(buffer)) !=-1) {
output.write(buffer, 0, len);
System.out.print("#");
countlen=countlen+len;
}
//
output.flush();
output.close();
input.close();
// s2.close();
// mess=br.readLine();
while (br.ready()==true) {
mess = br.readLine();
System.out.println(mess);
}
System.out.println("Done!");
System.out.println("Byte trasferiti: "+countlen);
[B]Non mi entra in quel maledetto while!
Se vado a vedere sul server di altervista il file che voglio inviare esiste ma è vuoto, cioè vedo l'icona ma pesa 0K e all'interno non c'è scritto niente.
Grazie mille in anticipo ragazzi!:)
banryu79
23-09-2010, 20:56
Scusa, non ho ben capito lo scenario:
-> il tuo codice statbilisce una connessione con il server di altervista.
-> stai eseguendo un upload (trasferisci un tuo file dal tuo sistema al server) o un download (trasferisci un file di altervista dal server al tuo sistema)?
A giudicare dal fatto che leggi da un input stream ottenuto dal Socket 's2' sembra che tu stia leggendo dei dati dal server che poi scrivi in un file output stream di cui è lecito a questo punto pensare si tratti di un file sul tuo sistema: dunque sembra che tu stia eseguendo un download.
Ma se è così allora non riesco a trovare coerenza con questa tua affermazione:
Se vado a vedere sul server di altervista il file che voglio inviare esiste ma è vuoto, cioè vedo l'icona ma pesa 0K e all'interno non c'è scritto niente.
Puoi provare a riassumere in modo chiaro e schematico?
Perchè se il file su altervista pesa 0K ed è la sorgente dei dati dell'input stream forse è per questo che "nel while non entra": cioè ci entra ma appena va a verificare la condizione "(len = input.read(buffer)) !=-1" ci esce anche subito (dato che l'input stream ha come sorgente un file di 0K, viene subito incontrata la fine dello stream).
scusa se non mi sono spiegato bene , devo fare un upload di un mio file locale e metterlo sul server .
In sintesi i miei passi da fare sono:
- connetto al server tramite pasv -->fatto
- invio al server un mio file su locale --> mi pianto qui
Una volta che il codice viene eseguito l'output è:
Done! --> lo dice il mio programma
Byte trasferiti 0 --> lo dice il mio programma e le metto fuori dopo il while
" 150 connessione dati accettata" --> me lo dice il server perchè nel codicice successivo allo spezzone che ho postato ho una serie di readLine();
"420 Timeout" -->idem come sopra
"420 Trasferimento annullato" --> idem come sopra
Se vado a vedere sul server di altervista il file che voglio inviare esiste ma è vuoto, cioè vedo l'icona ma pesa 0K e all'interno non c'è scritto niente.
Capito la stranezza? vedo l'icona , mi dice che pesa 0 K ed è vuoto , supponiamo di inviare il file di testo "ciao.txt" , dopo l'esecuzione del codice vedremo sul server la presenza del file "ciao.txt" ma con al suo interno scritto niente.
Spero di essere stato più chiaro , grazie come sempre la la gentilezza e la disponibilità!
banryu79
24-09-2010, 08:56
Magari son io che svariono, ma quello che hai descritto in linguaggio naturale nel tuo post qua sopra appunto mi sembra non collimi con quello che il codice descrive nel primo post.
Cioè non evinco, nel codice del primo post, un tentivo di fare l'upload sul server di un file locale.
Tanto per essere sicuri: è giusto se dico che "s2" rappresenta una connessione con il canale di trasferimento dei dati?
Puoi postare nuovamente il codice?
Lo spezzone in cui fai quello che hai descritto nel post qui sopra?
Possibilmente identato bene, col tag CODE, così non rischiamo fraintendimenti.
Anzi, posta tutto il metodo in cui si trova quel codice, via.
E magari sotto, a parte, racchiuso dai tag QUOTE, l'output che il programma ti stampa quando lo mandi in esecuzione.
Così tagliamo la testa al toro :D
import java.io.*;
import java.net.*;
import java.util.*;
public class Client {
public static void main(String[] args) throws IOException {
String host = "idnob.altervista.org";
String user=null;
String pass=null;
String mess=null;
String filename = null;
String cmd=null,ip=null;
String linea;
String s1=null,h=null; // la uso per il port nel comando DIR
int porta=21,finalport=0;
BufferedReader brl; // Input locale
BufferedReader br; // Input rete da socket s
PrintStream pw; //Output rete su socket s
BufferedReader br2; //Input rete da s2
PrintStream pw2; //Output rete su s2
DataInputStream in; // Input dati da socket s2
BufferedOutputStream output; //Stream invio file
int i=0,c=0,u=0,p=0; //per il login
Socket s = new Socket (host , porta);
//Inizializzo input locale
brl = new BufferedReader(new InputStreamReader(System.in));
//input da rete
br = new BufferedReader (new InputStreamReader (s.getInputStream()));
//output su rete
pw = new PrintStream (s.getOutputStream());
// teoricamente per mandare files
in = new DataInputStream (s.getInputStream());
//ricezione del messaggio del server , se arriva un 220 ok senò errore
mess = br.readLine();
if ( !mess.startsWith("220 ")) {System.out.println("Errore nell'esecuzione del comando "+mess);}
mess = br.readLine();
System.out.println(mess);
//il seguente while lo uso per leggere tutto ciò che ha da dire il server
while (br.ready()==true) {
mess = br.readLine();
System.out.println(mess);
}
//parte la login
do {
System.out.print("Username : ");
user = brl.readLine();
pw.println("USER "+user); //Invio User
mess = br.readLine(); //ricezione messaggio del sever , 331 OK
System.out.println(mess);
if (mess.substring(0, 3).equals("331")) { System.out.println("OK");u=1;}
else { System.out.println("Errore User");u=0;}
while (br.ready()==true) {
mess = br.readLine();
System.out.println(mess);
}
System.out.println("Inserire Password : ");
pass = brl.readLine();
pw.println("PASS "+pass);
mess = br.readLine(); //ricezione messaggio del sever , se arriva un 220 ok ,sen� pass sbagliata
System.out.println(mess);
if (mess.substring(0, 3).equals("230")) { System.out.println("OK");p=1; }
else { System.out.println("Errore in fase di Autenticazione");p=0; }
while (br.ready()==true) {
mess = br.readLine();
System.out.println(mess);
}
} while (!( (u==1) && (p==1) ) );
//qui la login è finita
// A questo punto l'utente � connesso
System.out.println("-----------------------------------------------------------------------------");
System.out.println("Porta di connessione CLIENT : "+s.getLocalPort());
System.out.println("Porta di connessione SERVER : "+s.getPort());
System.out.println("IP locale :"+s.getLocalAddress());
do{
System.out.println("Ftp >");
cmd = brl.readLine();
//faccio un if generale che guarda il comando immesso dall'utente
//in questo caso il comando è il send-->stor
if ( (cmd.equals("send")) || (cmd.equals("put")) ) {
// Setto la trasmissione passiva
cmd = "pasv";
pw.println(cmd);
mess = br.readLine();
System.out.println(mess);
//faccio il parsing del pasv
int i1=0,i2=0,port=0;String[] pasv=null;String virgola=",";String server;
i1 = mess.indexOf('(')+1; //prendo il primo indice inizio
i2 = mess.indexOf(')'); //prendo il secondo indice fine
pasv = mess.substring(i1,i2).split(virgola); //prendo il testo e lo divido ogni ','
server = (pasv[0]+"."+pasv[1]+"."+pasv[2]+"."+pasv[3]); //formatto server
port = Integer.parseInt(pasv[4]); // prendo la penultima parte ip pasv
finalport = ((port*256)+Integer.parseInt(pasv[5])); // calcolo la porta 256*penultima parte pasv + ultima parte pasv
System.out.println("IP "+server+" porta "+finalport);
/*debug per vedere host
InetAddress ia = InetAddress.getByName(server);
System.out.println(ia.getHostName());
*/
//setto la modalità di trasmissione binaria
cmd = "type i";
pw.println(cmd);
mess=br.readLine();
while (br.ready()==true) {
mess = br.readLine();
System.out.println(mess);
}
//uso un file di testo come esempio
filename = "ciao.txt";
//invio il comando stor
cmd = "STOR "+filename;
pw.println(cmd);
// mess = br.readLine();
while (br.ready()==true) {
mess = br.readLine();
System.out.println(mess);
} System.out.println("cippa");
//Apro la socket sul canale dati calcolato con PASV
Socket s2 = new Socket (server,finalport);
//inizializzo gli stream sulla nuova socket , mi accorgo adesso che sono inutili
br2 = new BufferedReader (new InputStreamReader (s2.getInputStream())); pw2 = new PrintStream (s2.getOutputStream());
//Resto in ascolto
while (br2.ready()==true) {
mess = br2.readLine();
System.out.println(mess);
}
// Definisco gli stream per invio sulla nuova Socket
BufferedInputStream input = new BufferedInputStream(s2.getInputStream());
output = new BufferedOutputStream(new FileOutputStream(filename));
// Setto i parametri per l'upload
final int BUFFER_SIZE = 4096;
byte[] buffer = new byte[BUFFER_SIZE];
int countlen=0;
int len = 0;
//Parte l'upload
int f=0;
while ((len = input.read(buffer)) !=-1) {
output.write(buffer, 0, len);
System.out.print("#");
countlen=countlen+len;
}
output.flush();
output.close();
input.close();
s2.close();
// mess=br.readLine();
while (br.ready()==true) {
mess = br.readLine();
System.out.println(mess);
}
System.out.println("Done!");
System.out.println("Byte trasferiti: "+countlen);
} //fine IF SEND
if ( (cmd.equals("list")) || (cmd.equals("LIST")) ) { //utilizzo PORT
s1 = "";
h = s.getInetAddress().getLocalHost().getHostAddress();
for (i=1;i<h.length();i++){
if(h.charAt(i)=='.')
{s1+=',';}
else { s1+=h.charAt(i);}
}
cmd = "list";
pw.println(cmd);
mess = br.readLine();
while (br.ready()==true) {
mess = br.readLine();
System.out.println(mess);
}
} // fine IF LIST
else{ //se il comando non è tra quelli dati
pw.println(cmd); //invio il comando
mess = br.readLine();
System.out.println(mess);
while (br.ready()==true) {
mess = br.readLine();
System.out.println(mess);
}
} // fine ELSE
if (mess.startsWith("421")){ cmd = "quit"; } //in caso di timeout
} while (! (cmd.equals("quit")) || (cmd.equals("bye")) || (cmd.equals("exit")) );
}
}
227 Entering Passive Mode (188,40,83,138,208,63)
IP 188.40.83.138 porta 53311
150 Connessione dati accettata
Done!
Byte trasferiti: 0
226-Timeout
226 Trasferimento annullato
Grazie mille per la pazienza, una birra è il minimo :)
banryu79
24-09-2010, 10:46
Birra accettata.
Sono di Padova, se un giorno caschi nei paraggi avvertimi :D
Per il codice, pazienta, appena ho tempo gli do un occhio...
Affare fatto , io sono di reggio emilia .
Certo che paziento , stai facendo oltrre il possibile , gentilissimo come sempre...
banryu ho risolto per il sending dei files , avevo sbagliato a dichiarare gli stream !
Adesso ho l'ultimo passo e sono aposto :
Se invio un file sul server che esiste già dovrei chiedere all'utente se sovrascriverlo o annullare , esistono metodi per quello ?
Dai che è l'utima fatica , intanto grazie di tutto!
banryu79
28-09-2010, 12:34
EDIT: doppio, vedi sotto
banryu79
28-09-2010, 12:36
banryu ho risolto per il sending dei files , avevo sbagliato a dichiarare gli stream !
Adesso ho l'ultimo passo e sono aposto :
Se invio un file sul server che esiste già dovrei chiedere all'utente se sovrascriverlo o annullare , esistono metodi per quello ?
Dai che è l'utima fatica , intanto grazie di tutto!
Ops... questo thread mi era proprio passato di mente (e di recente ho completamente brasato via la cache del mio browers), sorry :D
Per chiedere all'utente una risposta del tipo sì/no ci sono diversi modi. Intanto bisogna vedere se stai scrivendo una applicazione a consolle oppure un'applicazione a interfaccia grafica.
Nel primo caso basta che stampi un messaggio sullo standard output e subito dopo ti metti in ascolto sullo standard input per leggere la risposta.
Nel secondo caso, se usi Swing come framework per l'interfaccia grafica, c'è la comoda classe javax.swing.JOptionPane che espone dei metodi statici utili proprio per presentare delle finestre di dialogo con messaggi/richieste di conferma all'utente. Nel tuo caso fai comparire una finestra di conferma del tipo Sì/No (oppure Ok/Annulla) con un messaggio per l'utente e sei a posto.
Non ho capito se era questo il tuo dubbio?
Attento , niente birra senò :)
Il mio problema è capire se un file sul server esiste già o no , in base a quello chiedo all'utente se vuole sovrascrivere.(la richiesta e la lettura della risposta so gia farla).
Grazie mille intanto!
banryu79
28-09-2010, 15:37
Ah, in questo caso la risposta ce l'hai sotto il naso, o meglio gli occhi: sei connesso a un server ftp e puoi parlare con lui solo in ftpese.
C'è il comando ftp NLST che inviato al server restituisce una lista contentente i nomi di tutti i files e le cartelle presenti in una data cartella (di solito quella nota come present working directory)
In caso avessi bisogno di sapere quale è la present working directory esiste un comando apposito: PWD
Qui (http://en.wikipedia.org/wiki/List_of_FTP_commands) trovi una lista dei comandi ftp.
La mia idea grazie al tuo suggerimento era questa :
siccome devo fare anche il comando LIST procederei così:
Per il LIST :
- Ricevo il file di testo che mi manda il server , lo scorro e lo metto in output .
Per il SEND :
- Richiamo LIST e controllo se nel file di testo che ricevo compare la stringa corrispondente al file da uploadare , se c'è chiedo di sovrascrivere.
Ti sembra una buona idea?
Per ricevere un file dal server faccio il contrario rispetto al send per quanto riguarda gli stream?
DAi che ci siamo quasi maestro!
(siamo a 2 birre ) :)
banryu79
29-09-2010, 08:23
C'è una certa differenza tra il comando LIST e NLST.
Il fatto è che a LIST il server risponde con delle informazioni relative ad un file o cartella specifico (se richiesto) altrimenti con info relative alla pwd.
Queste info posso essere formattate come meglio crede il server, non c'è un formato standardizzato prestabilito.
[di solito infatti una libreria FTP include diversi parser proprio per leggere le risposte del comando LIST, alcune inoltre danno la possibilità all'utente-programmatore di definire dei custom parser e registrarli perchè possano essere usati dalla libreria]
Invece la risposta al comando NLST (list names) è molto semplice: una lista dei nomi di tutte le entry di una directory.
Se puoi scegliere tra i due, io ti consiglio di implementare NLST e lasciare perdere LIST.
Ok , ma non ho trovato il raw command corrispondente , cioè , al server non posso mandare direttamente nlst ma il suo raw corrispondente , quindi cosa gli invio?
banryu79
29-09-2010, 11:20
Non ci metto la mano sul fuoco ma che io sappia NLST è un "raw command". Verifica di usarlo nel modo previsto, cioè rispettandone la sintassi.
Forse questo link (http://www.nsftools.com/tips/RawFTP.htm) può esserti d'aiuto.
Ma per andare sul sicuro devi rivolgerti alle RFC.
In fondo a questa pagina (http://en.wikipedia.org/wiki/List_of_FTP_commands)trovi dei link diretti, senza che ti sbracci troppo sul sito della IETF.
Grazie , i siti li avevo visti , l'inghippo è che in altervista ad esempio (come su netsons) non si può utilizzare , è permesso solo il LIST .
A questo punto invece di fare il comando list faccio il comando get che mi sembra più facile così ho finito.
Per fare il get faccio al contrario rispetto allo STOR ?
cioè il contrario di :
FileInputStream input = new FileInputStream(file);
output = new BufferedOutputStream(s2.getOutputStream());
cioè :
FileInputStream input = new FileInputStream(s2.getInputStream);
output = new BufferedOutputStream(file);
?
vBulletin® v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.