Upload de Imagem para Servidor

13 respostas
androidjava
T

Prezados, gostaria de saber como salvar Imagem no Servidor (FTP)?
Estou desenvolvendo um App onde seleciono uma imagem local e queria enviar (salvar) em um diretório de um servidor (Hostinger) que tenho e não sei como faze-lo.

Alguém poderia me ajudar?

Obrigado.

13 Respostas

F

Um jeito bem tranquilo é converter a imagem pra uma String base 64 e mandar essa string para o servidor. Outra forma é mandar o array de bytes da sua imagem para o servidor.

T

Felipe muito obrigado pelo retorno.
Eu já tentei fazer desta forma nas, provavelmente estou cometendo algum erro.

Você teria um exemplo que eu possa seguir?

Obrigado.

F

Posta seu código, os problemas que está tendo e eu dou uma olhada.

L

Thiago,

No meu primeiro app Android eu tive que fazer essa tarefa, envio de arquivo para o ftp:
Eu usei as seguintes bibliotecas:

commons-net-3.1.jar
commons-io-2.4.jar`

Vou postar  parte do código,  uma adaptada nele:

`import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.SocketException;
import java.net.UnknownHostException;

import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPReply;
import android.app.ProgressDialog;
import android.content.Context;
import android.os.AsyncTask;
import android.util.Log;

public class EnviaArquivoFtp extends AsyncTask<File, String, String> {

	private static final String TAG = "EnviaArquivoFtp";
	private ProgressDialog dialog;
	private Context context;

	public EnviaArquivoFtp(Context context) {
		this.context = context;
	}
	
	@Override
	protected void onPreExecute() {
		super.onPreExecute();
		
		dialog = ProgressDialog.show(context, context.getString(R.string.app) , "Iniciando o envio dos arquivos para o servidor...");
	}
	
	@Override
	protected void onPostExecute(String result) {
		super.onPostExecute(result);
		
		dialog.dismiss();		
	}
	
	@Override
	protected void onProgressUpdate(String... values) {
		super.onProgressUpdate(values);
		dialog.setMessage(values[0]);
	}

	@Override
	protected String doInBackground(File ... files) {
		File f = files[0];
		
		try {
			FTPClient ftp = new FTPClient();
					
			if (ftp.isAvailable()) {
				//servidor indisponivel
				return null;
			}
			
			ftp.connect("ftp://xxx.xxx.xx......", FTPClient.DEFAULT_PORT);	
			boolean retornoLogin = ftp.login(usuario, senha);
			
			if (retornoLogin == false) {
				//erro ao tentar efetuar login
				return null;
			}
			
			boolean mudaDiretorioCorrente = false;
			
			try {
				//Retorna false caso o diretorio informado seja invalido
				mudaDiretorioCorrente = ftp.changeWorkingDirectory(diretorioNoFTP);
				
			} catch (Exception ex) {
				Log.e(TAG, ex.getMessage());
			}
			
			if (!mudaDiretorioCorrente) {
                                //diretório não existe
				return null;
			}
			
			FileInputStream fis = new FileInputStream(f);							
			publishProgress("Enviando o arquivo " + f.getName() + " para o servidor");
			ftp.setFileTransferMode(FTPClient.BINARY_FILE_TYPE);
			ftp.setFileType(FTPClient.BINARY_FILE_TYPE);
			ftp.setControlKeepAliveTimeout(300);
			ftp.enterLocalPassiveMode();
						
			boolean retornoEnvio = ftp.storeFile(f.getName(), fis);
			fis.close();		
					
			return  msgSucesso;

		} catch (SocketException e) {
			Log.e(getClass().getSimpleName(), e.getMessage());

		} catch (IOException e) {
			Log.e(getClass().getSimpleName(), e.getMessage());

		} catch (Exception e) {
			Log.e(getClass().getSimpleName(), e.getMessage());

		} finally {
			loguot(ftp);
			fecharDesconectarFtp(ftp);
			
		}

		return context.getString(R.string.ocorreu_erro_durante_envio);
	}
	
	public static void loguot(FTPClient ftpClient) {
		try {
			ftpClient.logout();
		} catch (IOException e) {
			Log.e(getClass().getSimpleName(), e.getMessage());
		}
	}
	
	public static void fecharDesconectarFtp(FTPClient ftpClient) {
		if (ftpClient != null && ftpClient.isConnected()) {
			try {
				ftpClient.disconnect();
			} catch (IOException e) {
				Log.e(getClass().getSimpleName(), e.getMessage());
			}
		}
	}
}
T

Levi, obrigado pelo retorno.
Estou tentando usar seu exemplo e estou fazendo conforme abaixo:

Neste ponto chamo a função para fazer Upload da Imagem que está um um ImageView.
Mas não sei como pegar a imagem do ImagemView e passa-la para o AsynkTask como File.

xBtnTermoUso = (TextView) findViewById(R.id.btn_termoUso);
        xBtnTermoUso.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                UploadImage uploadImage =  new UploadImage();
                uploadImage.execute(bitmap)

            }
        });

Essa chamada deveria passar um File para a função abaixo:

package br.com.tapanovisual.tvisual.funcoes;

import android.os.AsyncTask;

import org.apache.commons.net.ftp.FTPClient;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;

//Created by thiago.c.melo on 08/08/2016.
public class UploadImage extends AsyncTask<File, String, String> {

    @Override
    protected String doInBackground(File ... files) {

        File file = files[0];
        String usuario = "****";
        String senha = "****";

        FTPClient ftp = new FTPClient();

        if (ftp.isAvailable()) {
            //servidor indisponivel
            return null;
        }

        try {
            ftp.connect("ftp://xxx.xxx.xx......", FTPClient.DEFAULT_PORT);
            boolean retornoLogin = ftp.login(usuario, senha);

            if (retornoLogin == false) {
                //erro ao tentar efetuar login
                return null;
            }

            FileInputStream fis = new FileInputStream(file);
            publishProgress("Enviando o arquivo " + file.getName() + " para o servidor");
            ftp.setFileTransferMode(FTPClient.BINARY_FILE_TYPE);
            ftp.setFileType(FTPClient.BINARY_FILE_TYPE);
            ftp.setControlKeepAliveTimeout(300);
            ftp.enterLocalPassiveMode();

            boolean retornoEnvio = ftp.storeFile(file.getName(), fis);
            fis.close();

            return  null;


        } catch (IOException e) {
            e.printStackTrace();
        }


        return null;
    }
}

Poderia me ajudar nesse ponto e avaliar se meu código está integro.
Muito obrigado.

L

Thiago,

De onde vc está carregando a imagem (web service, sdcard, etc)?
Dependendo de como vc estiver carregando a imagem vc pode passar o caminho completo da imagem ao invés de um arquivo, daí vc cria o File dentro do Asynctask, ex:

<a class="mention" href="/u/override">@Override</a>

protected String doInBackground(String  fullPath) {

File f = new File(fullPath[0]);
try {
	FTPClient ftp = new FTPClient();
			
	if (ftp.isAvailable()) {
		//servidor indisponivel
		return null;
	}
	
	ftp.connect("ftp://xxx.xxx.xx......", FTPClient.DEFAULT_PORT);	
	boolean retornoLogin = ftp.login(usuario, senha);
	
	if (retornoLogin == false) {
		//erro ao tentar efetuar login
		return null;
	}
	
	boolean mudaDiretorioCorrente = false;
	
	try {
		//Retorna false caso o diretorio informado seja invalido
		mudaDiretorioCorrente = ftp.changeWorkingDirectory(diretorioNoFTP);
		
	} catch (Exception ex) {
		Log.e(TAG, ex.getMessage());
	}
	
	if (!mudaDiretorioCorrente) {
        //diretório não existe
		return null;
	}
	
	FileInputStream fis = new FileInputStream(f);							
	//publishProgress("Enviando o arquivo " + f.getName() + " para o servidor");
	ftp.setFileTransferMode(FTPClient.BINARY_FILE_TYPE);
	ftp.setFileType(FTPClient.BINARY_FILE_TYPE);
	ftp.setControlKeepAliveTimeout(300);
	ftp.enterLocalPassiveMode();
				
	boolean retornoEnvio = ftp.storeFile(f.getName(), fis);
	fis.close();		
			
	return  msgSucesso;

} catch (SocketException e) {
	Log.e(getClass().getSimpleName(), e.getMessage());

} catch (IOException e) {
	Log.e(getClass().getSimpleName(), e.getMessage());

} catch (Exception e) {
	Log.e(getClass().getSimpleName(), e.getMessage());

} finally {
	loguot(ftp);
	fecharDesconectarFtp(ftp);
	
}

return context.getString(R.string.ocorreu_erro_durante_envio);

}

Só lembrando que existe alguns pontos que podem ser melhorado no código, como por exemplo:

  • Efetuar o upload dentro de um IntentService ao invés de Asynctask.
  • Fazer tratamento do retorno, pra exibir mensagem para o usuário, caso não seja possível conectar ao servidor FTP, ou caso o diretório que está tentando enviar o arquivo não exista, ou se o método ftp.storeFile retonar false (isso quer dizer que o upload falhou), enfim a uma série de melhorias que podem ser implementadas, mas isso não quer dizer que o código não funcione, mas dependendo do seu nível de experiência seja melhor deixar assim por enquanto.

Agora voltando ao início…
Como vc está fazendo o carregamento da imagem no ImageView, qual a fonte do arquivo de imagem?

T

Levi, muito obrigado pelas dicas e de fato essa melhorias serão implementadas é que primeiro eu quero fazer salvar a imagem…rsrs…e depois vou fazer os tratamentos de exceção.

Quanto a origem da imagem e será selecionada dentre as imagens que estão armazenadas no smartphone. Quando o usuário clicar em cima do ícone de foto o app abrira a galeria do celular. Após o usuário vai selecionar uma foto e esta foto será imputada em um ImageView.

Obs.: Até aí já esta funcionando.

Agora eu quero pegar essa imagem do ImageView e salva-la em um diretório da Hostinger.

Pelo que eu entendi…eu posso passar esse caminho (Filepath) como String para o AsynkTask e criar o File a partir dele e esse File eu salvo no diretório.

É isso?
Vou testar…obrigado!

T

Levi, funcionou!!!
Só mais uma coisa, sabe como eu posso definir o tamanho da imagem antes de salva-la?

Muito obrigado!!!

T

A imagem (File) esta muito grande. Teria como redimensionar a imagem antes de enviar para o servidor?
Obrigado.

F

Para redimensionar a imagem, basta usar a classe Bitmap.

Bitmap bm = Bitmap.createScaledBitmap(bitmap, ALTURA_EM_PX, LARGURA_EM_PX, true);

Sugestão: como redimensionamento de imagens é uma tarefa custosa para o processador, faça esse comando dentro do doInBackground da sua AsyncTask.

L

Thiago,

Acredito que a sugestão do Felipe atenda a sua necessidade.

T

Então…o problema é que eu estou com um file.
resumidamente…eu selecione uma imagem da galeria e setei em um imageview.

Através do caminho da imagem, que está no meu cel, criei um File file = New File (caminho). E daí salvo esse file no servidor.

Só que a imagem é muito grande e eu gostaria de diminuir.

Coloquei o file dentro de um Bitmap e diminui a imagem conforme a dica do Felipe…mas agora não consigo transformar em file novamente para enviar para o servidor.

Será que deu pra entender?..:grinning:

Muito obrigado pelas dicas!

F

Tranquilo. Só chamar o método compress:

File file = new File(caminho);
OutputStream stream = new BufferedOutputStream(new FileOutputStream(file));
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, stream);
stream.close();

Existem outras constantes para serem passadas no lugar do CompressFormat.JPEG, como CompressFormat.PNG por exemplo. Já o segundo argumento é a qualidade da compressão entre 0-100.

Criado 8 de agosto de 2016
Ultima resposta 18 de ago. de 2016
Respostas 13
Participantes 3