terça-feira, 12 de junho de 2012

Efetuando download via FTP

Olá pessoal,

Hoje vou mostrar como acessar um servidor FTP, utilizando android vou criar uma classe client FTP completa com todas as funcionalidades que você irá precisar como por exemplo listar arquivos, excluir, mudar de diretório, mas no exemplo prático será apresentada a rotina para efetuar um download via FTP.

Como de costume vou apresentar todos os fontes utilizados já com comentários para facilitar no aprendizado.

Abaixo segue um print dos arquivos do projeto:


Abaixo segue o arquivo clsFTP.java
package br.com.EscolaDeAndroid.FTP;

import java.io.FileInputStream;
import java.io.FileOutputStream;

import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPFile;
import org.apache.commons.net.ftp.FTPReply;

import android.util.Log;

public class clsFTP {
    FTPClient mFtp;  
    private String TAG = "clsFTP";

   
    //Listar os arquivos e diretórios de um determinado caminho
    public FTPFile[] Dir(String pDiretorio)
    {
        try {
            FTPFile[] ftpFiles = mFtp.listFiles(pDiretorio);

            return ftpFiles;
        } catch(Exception e) {
            Log.e(TAG, "Erro: não foi possível listar os arquivos e pastas do diretório " + pDiretorio + ". " + e.getMessage());
        }
        return null;
    }    
    
    //Pegar o nome do diretório corrente
    public String DiretorioCorrente()
    {
        try {
            String workingDir = mFtp.printWorkingDirectory();
            return workingDir;
        } catch(Exception e) {
            Log.e(TAG, "Erro: não foi possível obter o diretório atual. " + e.getMessage());
        }
        return null;
    }    
    
    //Mudar de diretório
    public boolean MudarDiretorio(String pDiretorio)
    {
        try {
            mFtp.changeWorkingDirectory(pDiretorio);
        } catch(Exception e) {
            Log.e(TAG, "Erro: não foi possível mudar o diretório para " + pDiretorio);
        }
        return false;
    }    
    
    //Criar um diretório
    public boolean CriarDiretorio(String pDiretorio)
    {
        try {
            boolean status = mFtp.makeDirectory(pDiretorio);
            return status;
        } catch(Exception e) {
            Log.e(TAG, "Erro: não foi possível criar o diretório " + pDiretorio);
        }
        return false;
    }    
    
    //Excluir um diretório
    public boolean RemoveDiretorio(String pDiretorio)
    {
        try {
            boolean status = mFtp.removeDirectory(pDiretorio);
            return status;
        } catch(Exception e) {
            Log.e(TAG, "Erro: não foi possível remover o diretório " + pDiretorio);
        }
        return false;
    }    
    
    //Deletar arquivo
    public boolean Delete(String pArquivo)
    {
        try {
            boolean status = mFtp.deleteFile(pArquivo);
            return status;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }    
    
    //Renomear arquivo
    public boolean Rename(String from, String to)
    {
        try {
            boolean status = mFtp.rename(from, to);
            return status;
        } catch (Exception e) {
            Log.e(TAG, "Erro: Não pode renomear o arquivo: " + from + " para: " + to);
        }
        return false;
    }    
    
    //Baixar um arquivo do servidor FTP
    public boolean Download(String pDiretorioOrigem, String pArqOrigem, String pArqDestino)  
    {  
        boolean status = false;  
        try {  
            MudarDiretorio(pDiretorioOrigem); 
            
            //Cria o outputStream para ser passado como parametro  
            FileOutputStream desFileStream = new FileOutputStream(pArqDestino);;  
              
            //Tipo de arquivo  
            mFtp.setFileType(FTP.BINARY_FILE_TYPE);  
              
            //http://commons.apache.org/net/apidocs/org/apache/commons/net/ftp/FTPClient.html#enterLocalActiveMode()  
            mFtp.enterLocalPassiveMode();  
              
            //Faz o download do arquivo  
            status = mFtp.retrieveFile(pArqOrigem, desFileStream);  
              
            //Fecho o output  
            desFileStream.close();  
    
            return status;  
        } catch (Exception e) {  
            Log.e(TAG, "Erro: Falha ao efetuar download. " + e.getMessage());  
        }  
        return status;  
    }
    
    //Enviar arquivo para o servidor FTP
    public boolean Upload(String pArqOrigem, String pArqDestino, String pDiretorioDestino)
    {
        boolean status = false;
        try {
            FileInputStream srcFileStream = new FileInputStream(pArqOrigem);

            //muda o diretório para o destino específico
            if (MudarDiretorio(pDiretorioDestino)) {
                status = mFtp.storeFile(pArqDestino, srcFileStream);
            }

            srcFileStream.close();
            return status;
        } catch (Exception e) {
            Log.e(TAG, "Erro: Falha ao efetuar Upload. " + e.getMessage());
        }
        return status;
    }
    
    //Encerrar a conexão com o servidor FTP
    public boolean Desconectar()
    {
        try {
            //mFtp.logout();
            mFtp.disconnect();
            mFtp = null;
            return true;
        } catch (Exception e) {
            Log.e(TAG, "Erro: ao desconectar. " + e.getMessage());
        }
        return false;
    }    
    
    //Efetuar conexão com o servidor FTP
    public boolean Conectar(String pHost, String pUsuario, String pSenha, int pPorta)
    {
        try {
            mFtp = new FTPClient();
            
            // conectando no host
            mFtp.connect(pHost, pPorta);
            
            //verifica se a conexão está ok
            if (FTPReply.isPositiveCompletion(mFtp.getReplyCode())) {
                
                //efetua login
                boolean status = mFtp.login(pUsuario, pSenha);

                mFtp.setFileType(FTP.BINARY_FILE_TYPE);
                mFtp.enterLocalPassiveMode();
                
                return status;
            }
        } catch(Exception e) {
            Log.e(TAG, "Erro: não foi possível conectar ao host " + pHost);
        }
        return false;
    }    
}

Abaixo segue o arquivo TesteFTPActivity.java:
package br.com.EscolaDeAndroid.FTP;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;

import android.app.Activity;
import android.os.Bundle;
import android.os.Environment;
import android.widget.EditText;
import android.widget.Toast;

public class TesteFTPActivity extends Activity {
    clsFTP mClienteFTP;
    EditText editText;
    
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        editText = (EditText)findViewById(R.id.editText1);
        String lstrArq = "";
        
        try {
            mClienteFTP = new clsFTP();
            
            //Definindo o nome do arquivo que será gravado no SD
            lstrArq = "/teste2.txt";
            File lArquivo = new File(Environment.getExternalStorageDirectory(), lstrArq); 
            
            mClienteFTP.Conectar("ftp.seuendereco.com", "usuario", "senha", 21);
            
            //Faz o download do arquivo passando o nome dele(dentro o servidor) e local onde ele vai ser guardado  
            mClienteFTP.Download("/nomedapasta", "teste.txt", lArquivo.toString());
              
            //Desconecta do ftp  
            mClienteFTP.Desconectar();          
            
            //Efetua a leitura do arquivo   
            FileReader fileReader= new FileReader(lArquivo);  
            BufferedReader leitor= new BufferedReader(fileReader);  
            String linha = null;    
              
            //Loop para ler e carregar o editText  
            while((linha = leitor.readLine()) != null) {    
                editText.append(linha);  
            }   
            
            leitor.close();
            fileReader.close();
                
        } catch (Exception e) {
            trace("Erro : " + e.getMessage());
        }
            
    }
    
    public void toast (String msg)
    {
        Toast.makeText (getApplicationContext(), msg, Toast.LENGTH_SHORT).show ();
    } 
     
    private void trace (String msg) 
    {
        toast (msg);
    }    
}

Abaixo segue o arquivo AndroidManifest.xml, onde deveremos adicionar as permissões para acessar a internet e gravar no SD:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="br.com.EscolaDeAndroid.FTP"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk android:minSdkVersion="7" />
 <uses-permission android:name="android.permission.INTERNET"/>
 <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name" >
        <activity
            android:name=".TesteFTPActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
</manifest>

Abaixo segue o arquivo main.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <EditText
        android:id="@+id/editText1"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:inputType="text"
        android:ems="10" >
        <requestFocus />
    </EditText>

</LinearLayout>

Por enquanto é isso pessoal, espero que seja útil esse projeto para vocês, e caso necessitem, por exemplo, enviar um arquivo via FTP, dentro da classe clsFTP.java já possui esse e outros métodos.



Desenvolvi o jogo Circus Puzzle Free ele é um quebra-cabeça e está publicado no Android Market, agradeço a todos que baixarem, jogarem e comentarem.



Desenv com qualidade!

14 comentários:

André Luís Kunde disse...

Parabéns pelo blog!

Os tutos são muito bons! Estão me ajudando bastante.

Eu acompanhei o exemplo da agenda, que tem uma tabela no banco de dados... você tem algum exemplo com mais de uma tabela??

Marcio de Souza disse...

Andre,

Pretendo postar sim, e que no momento estou sem tempo pois meu filho esta preste a nascer.

Assim que sobrar um tempinho eu posto.

Obrigado pelas visitas.

Edimar Gotardo disse...

Muito bom mesmo seu Blog...

Estamos ansiosos aguardando novos Posts...

Parabéns Pelo seu filho.

Tiago disse...

Muito bom!! Um ótimo blog.
Mas encontrei um problema, nas versões do android apartir do 3.2 ele da um erro: 'Connection is not open', utilizando esse mesmo código do post. mas na versão utilizada no post(2.1) como também nas versões 2.2 e 2.3(pelomenos que eu constatei), funciona normalmente.
Já procurei em vários blogs como resolver isso e não encontrei.
Acompanhei os posta sobre o listview e o de banco de dados que tambem são muito bons. Espero que possa me ajudar com essa questão.

Don Costa disse...

Ao editor
Tudo bom?
Cara, seguinte:
Sou fotojornalista e vivo na rua fazendo fotos de hard news para mandar para minha agencia comercializar.
Estou em busca de um sistema mais rapido para enviar minhas fotos. Uso um laptop com photoshop somente para abrir e salvar as fotos compactando em JPG, e modem 3G para enviar via programa de ftp - uso o file zilla.
Como tenho um tablet c/sistema android, queria saber contigo se conhece alguns programas para android que possa substituir esses que estou usando.
aguardo e agradeço
att
Julio Costa
jcostacosta@gmail.com

Sidney Toshidi disse...

Parabéns pelo código.
Mas tive um problema. O .txt coloquei em uma pasta no ftp como também mudei o caminho pelo código e acabou não dando certo. Conclui que o arquivo tem que estar na raiz, se estiver em outra pasta o download não é feito.
Então gostaria de saber como você faz para pegar .txt em outra pasta?

naruto disse...

Olá, parabéns pelo tutorial,
gostaria de uma ajuda, pois estou com um problema
com os diretórios, ele conecta mais não consigo mudar,
nem criar diretórios da uma força ai, agradecido desde já

Fernando Souza de Almeida disse...

Estou com erro ao mudar o diretorio

Rodrigo Fernandes Ricardo disse...

olá Marcio, parabéns pelo artigo, muito bem explicado.
Preciso de sua ajuda, implementei o projeto porém estou com problemas, quando o app vai conectar com o ftp ele simplesmente fecha, já troquei a lib mas até agora não consegui resolver.

Admim disse...

Como faço pra colocar um progressdialog monitorando quanto falta pra terminar o dowload?

ZInber disse...

Olá, queria saber qual é o melhor programa para desenvolver Apps para Android?

Luiz Emir disse...

ola sou Luiz Emir
Digitei a risca todo o tutorial e não funcionou deu erro commons parou

Luiz Emir disse...

Estou usando a versão 4. no android, e não deu o que preciso fazer, será podem me dar uma força.

Luiz Emir disse...

Se alguem tiver um upload que funcione bem no android 4.x por favor me passe uma dica ou tuotorial.