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.
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.
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.
Posta seu código, os problemas que está tendo e eu dou uma olhada.
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 aí parte do código, dá 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());
}
}
}
}
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.
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:
@Override
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?
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!
Levi, funcionou!!!
Só mais uma coisa, sabe como eu posso definir o tamanho da imagem antes de salva-la?
Muito obrigado!!!
A imagem (File) esta muito grande. Teria como redimensionar a imagem antes de enviar para o servidor?
Obrigado.
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
.
1 curtida
Thiago,
Acredito que a sugestão do Felipe atenda a sua necessidade.
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?..
Muito obrigado pelas dicas!
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.