Accesarea unui server FTP

Accesarea unui server FTP

Postby morpheus » 17 Jan 2011, 01:14

Accesarea unui server FTP din limbajul Java



1. Introducere



Acest exemplu detaliaza cum ne putem conecta la un server FTP folosind limbajul Java.
Pentru a realiza acest lucru ne putem folosi de biblioteca Apache Commons Net, disponibila la adresa: http://commons.apache.org/net/

Tool-uri necesare:
- Java JDK (preferabil versiunea 1.6)
- Apache Ant (disponibil la adresa http://ant.apache.org/), pentru partea de build
- Apache Ivy pentru rezolvarea dependentelor proiectului (singura fiind Apache Common Net). Este disponibil la adresa: http://ant.apache.org/ivy/

Trebuie ca jar-ul pentru Ivy sa fie in CLASSPATH (de exemplu, in cazul meu, am in CLASSPATH d:\OPENSOURCE\apache-ivy-2.2.0\ivy-2.2.0.jar)
Trebuie ca directorul bin din distributia de Ant sa fie in PATH

2. Detalii privind utilizarea bibliotecii Apache Commons Net



Pasi ce trebuiesc urmati:

1. Instantierea unui obiect de tipul FTPClient. Acesta va fi utilizat pentru a interactiona cu serverul FTP.
  1.  
  2. FTPClient client = new FTPClient();
  3.  


2. Folosind obiectul de tip FTPClient, ne putem conecta la serverul FTP
  1.  
  2. client.connect(server);
  3.  

unde parametrul metodei este numele serverului FTP (de exemplu ftp.gnu.org)
Pentru a testa faptul ca ne-am conectat cu succes, trebuie sa testam codul de replay obtinut in urma operatiei de conectare.
Pentru a obtine codul de replay, folosim metoda getReplayCode() a clasei FTPClient.
Pentru a testa codul de replay obtinut, folsim metoda isPositiveCompletion(), statica in clasa FTPReply.

O bucata de cod ce exemplifica cele doua operatii este urmatoarea:
  1.  
  2. int reply = client.getReplyCode();
  3. if(FTPReply.isPositiveCompletion(reply)) {
  4.     // serverul FTP a acceptat conexiunea
  5. } else {
  6.     // serverul FTP a refuzat conexiunea
  7. }
  8.  


3. Dupa ce ne-am conectat la server, trebuie sa initiem operatiunea de log-in
Pentru aceasta avem nevoie de un nume de utilizator si de o parola.
Folosim metoda login(), a clasei FTPClient.
  1.  
  2. client.login(user, password);
  3.  

 
4. Presupunand ca operatia de log-in a decurs cu succes, de acum putem efectua diverse operatii, precum:
 
a) Setarea directorului remote (pe serverul FTP)
Pentru aceasta, folosim metoda changeWorkingDirectory() a clasei FTPClient, ce primeste ca parametru numele noii cai.
  1.  
  2. client.changeWorkingDirectory(path)
  3.  


b) Obtinerea de informatii despre fisierele ce se gasesc pe serverul FTP in directorul remote
Se foloseste metoda listFiles() a clasei FTPClient. Metoda intoarce un array de obiecte de tipul FTPFile.
Clasa FTPFile impacheteaza informatii despre un fisier aflat pe serverul FTP (precum numele sau, drepturi de acces, dimensiune in octeti, etc).
  1.  
  2. client.listFiles();
  3.  


c) Download-ul unui fisier de pe server
Se poate folosi metoda retrieveFile() a clasei FTPClient. Metoda primeste doi parametri: numele fisierului remote (ce se doreste a fi download-at) si un stream de iesire (FileOutputStream) deschis local, in care va fi scris continutul fisierului.
  1.  
  2. FileOutputStream outStream = new FileOutputStream(localFile);
  3. client.retrieveFile(remoteFile, outStream)
  4.  

Metoda retrieveFile() intoarce true daca operatia de download a reusit.

d) Upload-ul unui fisier pe server
Se poate folosi metoda storeFile() a clasei FTPClient. Metoda primeste doi parametri: numele fisierului remote (cum se va numi fisierul upload-at pe server) si un stream de intrare (FileInputStream) corespunzator fisierului local ce va fi upload-at.
  1.  
  2. FileInputStream inputStream = new FileInputStream(localFile);
  3. client.storeFile(remoteFile, inputStream);
  4.  


In cazul operatiilor de transfer (download, upload), se poate specifica tipul transferului (binar, ASCII, ...).
Pentru aceasta se poate folosi metoda setFileType() a clasei FTPClient.
De exemplu, pentru a seta tipul transferului ca fiind binar, procedam astfel:
  1.  
  2. client.setFileType(FTP.BINARY_FILE_TYPE);
  3.  

Pentru a seta tipul transferului ca fiind ASCII:
  1.  
  2. client.setFileType(FTP.ASCII_FILE_TYPE);
  3.  


5. In cele din urma, trebuie sa ne deconectam de la server.
Acest lucru presupune executarea unei operatii de log-out:

si a operatiei de deconectare a clientului de la server:
  1.  
  2. client.disconnect();
  3.  


3. Exemplu complet



Sa punem totul cap la cap intr-un mic exemplu.

In acest exemplu, ne conectam la serverul FTP GNU, avand adresa ftp.gnu.org, in mod anonymous ( numele de utilizator fiind anonymous iar parola o adresa de email - nu conteaza care).
Dupa conectare, schimbam directorul remote curent catre gnu, luam lista de fisiere remote si o afisam.
Apoi, descarcam fisierul cu numele =README

Codul este urmatorul:
  1.  
  2.  
  3. package info.bitcell.javaexamples.ftp;
  4.  
  5. import java.io.IOException;
  6.  
  7. import org.apache.commons.net.ftp.FTPFile;
  8.  
  9. public class FtpClientDemo {
  10.     public static void main(String[] args) {
  11.         FtpClientSession client = new FtpClientSession();
  12.         try {
  13.             // connect to server ftp.gnu.org as anonymous
  14.             client.connect("ftp.gnu.org", "anonymous", "test@mail.org");
  15.             try {
  16.                 // change the remote directory to gnu
  17.                 client.chdir("gnu");
  18.                 // print the files info from the remote directory
  19.                 for (FTPFile ftpFile : client.listFiles()) {
  20.                     System.out.println(ftpFile);
  21.                 }
  22.                 // download the "=README" file from the server
  23.                 client.downloadFile("=README", "=README", false);
  24.             } finally {
  25.                 // disconnect from the server
  26.                 client.disconnect();
  27.             }
  28.         } catch (IOException ex) {
  29.             ex.printStackTrace();
  30.         }
  31.     }
  32. }
  33.  


Clasa FtpClientSession este folosita pentru a accesa serverul FTP.
Detaliile de implementare ar trebui sa fie clare deja.
  1.  
  2. package info.bitcell.javaexamples.ftp;
  3.  
  4. import org.apache.commons.net.ftp.FTP;
  5. import org.apache.commons.net.ftp.FTPClient;
  6. import org.apache.commons.net.ftp.FTPFile;
  7. import org.apache.commons.net.ftp.FTPReply;
  8.  
  9. import java.io.FileInputStream;
  10. import java.io.FileOutputStream;
  11. import java.io.IOException;
  12.  
  13. public class FtpClientSession {
  14.     /**
  15.      * The client used to connect to the FTP server
  16.      */
  17.     private final FTPClient client = new FTPClient();
  18.    
  19.     /**
  20.      * Connect to an FTP server
  21.      * @param server the server address (e.g "ftp.gnu.org")
  22.      * @param user the user
  23.      * @param password the password
  24.      * @throws IOException if the connection failed
  25.      */
  26.     public void connect(String server, String user, String password) throws IOException {
  27.         // connect to the server
  28.         client.connect(server);
  29.         // enter local passive mode, in case we are behind a firewall
  30.         client.enterLocalPassiveMode();
  31.         // see if the replay code of the connect operation is positive
  32.         int reply = client.getReplyCode();
  33.         if(!FTPReply.isPositiveCompletion(reply)) {
  34.             // the server refused the connection
  35.             client.disconnect();
  36.             throw new IOException("Server refused connection");
  37.         }
  38.         // we have successfully connected to the server, now proceed
  39.         // with the login
  40.         client.login(user, password);
  41.     }
  42.    
  43.     /**
  44.      * Disconnect from an FTP server
  45.      * @throws IOException if the disconnect command failed
  46.      */
  47.     public void disconnect() throws IOException {
  48.         assert(client.isConnected());
  49.         // first logout, then disconnect from the server
  50.         client.logout();
  51.         client.disconnect();
  52.     }
  53.    
  54.     /**
  55.      * Change the remote directory path
  56.      * @param path the new remote path
  57.      * @throws IOException if the command failed
  58.      */
  59.     public void chdir(String path) throws IOException {
  60.         if (!client.changeWorkingDirectory(path)) {
  61.             throw new IOException("Could change remote directory to " + path);
  62.         }
  63.     }
  64.    
  65.     /**
  66.      * Get the list of remote files
  67.      * @return the list of remote files
  68.      * @throws IOException if the command failed
  69.      */
  70.     public FTPFile[] listFiles() throws IOException {
  71.         assert(client.isConnected());
  72.         return client.listFiles();
  73.     }
  74.    
  75.     /**
  76.      * Download a remote file to the local host
  77.      * @param remoteFile the name of the remote file
  78.      * @param localFile the name of the local file
  79.      * @param binaryTransfer set to true if the transfer is binary
  80.      *        and to false if is ASCII
  81.      * @throws IOException if the command failed
  82.      */
  83.     public void downloadFile(String remoteFile, String localFile, boolean binaryTransfer) throws IOException {
  84.         assert(client.isConnected());
  85.         // set the transfer type to either binary or ASCII, depending
  86.         // on the binaryTransfer parameter
  87.         boolean fileTypeResult;
  88.         if (binaryTransfer) {
  89.             fileTypeResult = client.setFileType(FTP.BINARY_FILE_TYPE);
  90.         } else {
  91.             fileTypeResult = client.setFileType(FTP.ASCII_FILE_TYPE);
  92.         }
  93.         // check if the transfer type was set correctly
  94.         if (!fileTypeResult) {
  95.             throw new IOException("Could not set the file transfer type");
  96.         }
  97.         // now proceed with the download
  98.         FileOutputStream outStream = new FileOutputStream(localFile);
  99.         if (!client.retrieveFile(remoteFile, outStream)) {
  100.             throw new IOException("Could not download file " + remoteFile);
  101.         }
  102.     }
  103.    
  104.     /**
  105.      * Download a remote file to the local host
  106.      * The transfer type is ASCII
  107.      * @param remoteFile the name of the remote file
  108.      * @param localFile the name of the local file
  109.      * @throws IOException if the command failed
  110.      */
  111.     public void downloadFile(String remoteFile, String localFile) throws IOException {
  112.         downloadFile(remoteFile, localFile, false);
  113.     }
  114.    
  115.     /**
  116.      * Upload a local file to the server
  117.      * @param localFile the path of the local file
  118.      * @param remoteFile the path of the remote file
  119.      * @param binaryTransfer set to true if the transfer is binary and
  120.      *        to false if is ASCII
  121.      * @throws IOException if the command failed
  122.      */
  123.     public void uploadFile(String localFile, String remoteFile, boolean binaryTransfer) throws IOException {
  124.         assert(client.isConnected());
  125.         boolean fileTypeResult;
  126.         // set the transfer type to either binary or ASCII, depending
  127.         // on the binaryTransfer parameter
  128.         if (binaryTransfer) {
  129.             fileTypeResult = client.setFileType(FTP.BINARY_FILE_TYPE);
  130.         } else {
  131.             fileTypeResult = client.setFileType(FTP.ASCII_FILE_TYPE);
  132.         }
  133.         // check if the transfer type was set correctly
  134.         if (!fileTypeResult) {
  135.             throw new IOException("Could not set the file transfer type");
  136.         }
  137.         // now proceed with the upload
  138.         FileInputStream inputStream = new FileInputStream(localFile);
  139.         if (!client.storeFile(remoteFile, inputStream)) {
  140.             throw new IOException("Could not upload file " + localFile);
  141.         }
  142.     }
  143.    
  144.     /**
  145.      * Upload a local file to the server
  146.      * The transfer type is ASCII
  147.      * @param localFile the path of the local file
  148.      * @param remoteFile the path of the remote file
  149.      * @throws IOException if the command failed
  150.      */
  151.     public void uploadFile(String localFile, String remoteFile) throws IOException {
  152.         uploadFile(localFile, remoteFile, false);
  153.     }
  154. }
  155.  


Biblioteca Apache Commons Net permite interactiunea cu mai multe protocoale, nu numai FTP:
  1.  
  2. NNTP
  3. SMTP
  4. POP3
  5. Telnet
  6. TFTP
  7. Finger
  8. Whois
  9. rexec/rcmd/rlogin
  10. Time (rdate) and Daytime
  11. Echo
  12. Discard
  13. NTP/SNTP
  14.  


Pentru mai multe detalii se poate consulta documentatia javadoc, disponibila pe site.

4. Compilare si rulare



Layout-ul proiectului este urmatorul:

  1.  
  2. │   build.xml
  3. │   ivy.xml
  4. ├───lib
  5. └───src
  6.     └───info
  7.         └───bitcell
  8.             └───javaexamples
  9.                 └───ftp
  10.                         FtpClientDemo.java
  11.                         FtpClientSession.java
  12.  


Compilarea si executia se poate face folosind urmatorul script Ant (build.xml):

  1.  
  2. <project xmlns:ivy="antlib:org.apache.ivy.ant" name="FtpClientDemo" basedir="." default="main">
  3. <taskdef resource="org/apache/ivy/ant/antlib.xml" />
  4.     <property name="src.dir"     value="src"/>
  5.     <property name="build.dir"   value="bin"/>
  6.     <property name="classes.dir" value="${build.dir}/classes"/>
  7.     <property name="jar.dir"     value="${build.dir}/jar"/>
  8.     <property name="main-class"  value="info.bitcell.javaexamples.ftp.FtpClientDemo"/>
  9.     <property name="lib.dir"     value="lib"/>
  10.     <property name="out.file"    value="=README"/>
  11.    
  12.    
  13.     <path id="classpath">
  14.         <fileset dir="${lib.dir}" includes="**/*.jar"/>
  15.     </path>
  16.  
  17.     <target name="clean">
  18.         <delete dir="${build.dir}"/>
  19.         <delete file="${out.file}"/>
  20.     </target>
  21.    
  22.     <target name="resolve" description="--> retrieve dependencies with ivy">
  23.         <ivy:retrieve />
  24.     </target>
  25.  
  26.     <target name="compile" depends="resolve">
  27.         <mkdir dir="${classes.dir}"/>
  28.         <javac srcdir="${src.dir}" destdir="${classes.dir}" classpathref="classpath" />
  29.     </target>
  30.  
  31.     <target name="jar" depends="compile">
  32.         <mkdir dir="${jar.dir}"/>
  33.         <jar destfile="${jar.dir}/${ant.project.name}.jar" basedir="${classes.dir}">
  34.             <manifest>
  35.                 <attribute name="Main-Class" value="${main-class}"/>
  36.             </manifest>
  37.         </jar>
  38.     </target>
  39.  
  40.     <target name="run" depends="jar">
  41.         <java fork="true" classname="${main-class}">
  42.             <classpath>
  43.                 <path refid="classpath"/>
  44.                 <path location="${jar.dir}/${ant.project.name}.jar"/>
  45.             </classpath>
  46.         </java>
  47.     </target>
  48.  
  49.     <target name="clean-build" depends="clean,jar"/>
  50.     <target name="main" depends="clean,run"/>
  51.  
  52. </project>
  53.  


Scriptul Ivy (ivy.xml) este urmatorul:

  1.  
  2. <ivy-module version="2.2">
  3.     <info organisation="info.bitcell" module="javaexamples"/>
  4.     <dependencies>
  5.         <dependency org="commons-net" name="commons-net" rev="2.2" />
  6.     </dependencies>
  7. </ivy-module>
  8.  


Se deschide un Command Prompt in directorul in care se afla fisierul build.xml si se ruleaza comanda:


In urma executiei, se vor compila fisierele sursa, se va genera arhiva FtpClientDemo.jar si se va executa.

Pentru a sterge binarele (*.class, *.jar) si fisierul descarcat de pe serverul FTP, se ruleaza comanda:
5.5p / 2 votes
User avatar
morpheus
Word
 
Joined: 30 Dec 2009
Location: Bucharest, Romania
Status: 54.84

Return to Exemple Java

Who is online

Users browsing this forum: No registered users and 0 guests