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