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.
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.
ThiagoCMelo
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.
FelipeTorres
Posta seu código, os problemas que está tendo e eu dou uma olhada.
Levi_Silva_Mendes
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.jarcommons-io-2.4.jar`Voupostaraípartedocódigo,dáumaadaptadanele:`importjava.io.File;importjava.io.FileInputStream;importjava.io.IOException;importjava.net.SocketException;importjava.net.UnknownHostException;importorg.apache.commons.net.ftp.FTPClient;importorg.apache.commons.net.ftp.FTPReply;importandroid.app.ProgressDialog;importandroid.content.Context;importandroid.os.AsyncTask;importandroid.util.Log;publicclassEnviaArquivoFtpextendsAsyncTask<File,String,String>{privatestaticfinalStringTAG="EnviaArquivoFtp";privateProgressDialogdialog;privateContextcontext;publicEnviaArquivoFtp(Contextcontext){this.context=context;}@OverrideprotectedvoidonPreExecute(){super.onPreExecute();dialog=ProgressDialog.show(context,context.getString(R.string.app),"Iniciando o envio dos arquivos para o servidor...");}@OverrideprotectedvoidonPostExecute(Stringresult){super.onPostExecute(result);dialog.dismiss();}@OverrideprotectedvoidonProgressUpdate(String...values){super.onProgressUpdate(values);dialog.setMessage(values[0]);}@OverrideprotectedStringdoInBackground(File...files){Filef=files[0];try{FTPClientftp=newFTPClient();if(ftp.isAvailable()){//servidor indisponivelreturnnull;}ftp.connect("ftp://xxx.xxx.xx......",FTPClient.DEFAULT_PORT);booleanretornoLogin=ftp.login(usuario,senha);if(retornoLogin==false){//erro ao tentar efetuar loginreturnnull;}booleanmudaDiretorioCorrente=false;try{//Retorna false caso o diretorio informado seja invalidomudaDiretorioCorrente=ftp.changeWorkingDirectory(diretorioNoFTP);}catch(Exceptionex){Log.e(TAG,ex.getMessage());}if(!mudaDiretorioCorrente){//diretório não existereturnnull;}FileInputStreamfis=newFileInputStream(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();booleanretornoEnvio=ftp.storeFile(f.getName(),fis);fis.close();returnmsgSucesso;}catch(SocketExceptione){Log.e(getClass().getSimpleName(),e.getMessage());}catch(IOExceptione){Log.e(getClass().getSimpleName(),e.getMessage());}catch(Exceptione){Log.e(getClass().getSimpleName(),e.getMessage());}finally{loguot(ftp);fecharDesconectarFtp(ftp);}returncontext.getString(R.string.ocorreu_erro_durante_envio);}publicstaticvoidloguot(FTPClientftpClient){try{ftpClient.logout();}catch(IOExceptione){Log.e(getClass().getSimpleName(),e.getMessage());}}publicstaticvoidfecharDesconectarFtp(FTPClientftpClient){if(ftpClient!=null&&ftpClient.isConnected()){try{ftpClient.disconnect();}catch(IOExceptione){Log.e(getClass().getSimpleName(),e.getMessage());}}}}
ThiagoCMelo
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.
Essa chamada deveria passar um File para a função abaixo:
packagebr.com.tapanovisual.tvisual.funcoes;importandroid.os.AsyncTask;importorg.apache.commons.net.ftp.FTPClient;importjava.io.File;importjava.io.FileInputStream;importjava.io.IOException;//Created by thiago.c.melo on 08/08/2016.publicclassUploadImageextendsAsyncTask<File,String,String>{@OverrideprotectedStringdoInBackground(File...files){Filefile=files[0];Stringusuario="****";Stringsenha="****";FTPClientftp=newFTPClient();if(ftp.isAvailable()){//servidor indisponivelreturnnull;}try{ftp.connect("ftp://xxx.xxx.xx......",FTPClient.DEFAULT_PORT);booleanretornoLogin=ftp.login(usuario,senha);if(retornoLogin==false){//erro ao tentar efetuar loginreturnnull;}FileInputStreamfis=newFileInputStream(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();booleanretornoEnvio=ftp.storeFile(file.getName(),fis);fis.close();returnnull;}catch(IOExceptione){e.printStackTrace();}returnnull;}}
Poderia me ajudar nesse ponto e avaliar se meu código está integro.
Muito obrigado.
Levi_Silva_Mendes
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:
try{FTPClientftp=newFTPClient();if(ftp.isAvailable()){//servidor indisponivelreturnnull;}ftp.connect("ftp://xxx.xxx.xx......",FTPClient.DEFAULT_PORT);booleanretornoLogin=ftp.login(usuario,senha);if(retornoLogin==false){//erro ao tentar efetuar loginreturnnull;}booleanmudaDiretorioCorrente=false;try{//Retorna false caso o diretorio informado seja invalidomudaDiretorioCorrente=ftp.changeWorkingDirectory(diretorioNoFTP);}catch(Exceptionex){Log.e(TAG,ex.getMessage());}if(!mudaDiretorioCorrente){//diretório não existereturnnull;}FileInputStreamfis=newFileInputStream(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();booleanretornoEnvio=ftp.storeFile(f.getName(),fis);fis.close();returnmsgSucesso;}catch(SocketExceptione){Log.e(getClass().getSimpleName(),e.getMessage());}catch(IOExceptione){Log.e(getClass().getSimpleName(),e.getMessage());}catch(Exceptione){Log.e(getClass().getSimpleName(),e.getMessage());}finally{loguot(ftp);fecharDesconectarFtp(ftp);}returncontext.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?
ThiagoCMelo
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!
ThiagoCMelo
Levi, funcionou!!!
Só mais uma coisa, sabe como eu posso definir o tamanho da imagem antes de salva-la?
Muito obrigado!!!
ThiagoCMelo
A imagem (File) esta muito grande. Teria como redimensionar a imagem antes de enviar para o servidor?
Obrigado.
FelipeTorres1 like
Para redimensionar a imagem, basta usar a classe Bitmap.
Sugestão: como redimensionamento de imagens é uma tarefa custosa para o processador, faça esse comando dentro do doInBackground da sua AsyncTask.
Levi_Silva_Mendes
Thiago,
Acredito que a sugestão do Felipe atenda a sua necessidade.
ThiagoCMelo
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!
FelipeTorres
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.