Envio de formulário Android com Bitmap para Servidor PHP
Blog /Android /Envio de formulário Android com Bitmap para Servidor PHP
(10242) (44)
Código de 20% de desconto no site da Editora NOVATEC: THIENGO
Nesse vídeo mostro como enviar um formulário do Android para um servidor PHP, porém dessa vez mostro como fazer para enviar também nesse formulário uma imagem (Bitmap). Muitos seguidores do blog solicitaram que fosse apresentado como enviar um bitmap para um servidor PHP, então mesmo já tendo mostrado como enviar um formulário do Android para um servidor PHP achei muito necessário voltar e abordar esse assunto, pois realmente não é trivial trabalhar com o envio de imagens do Android para outros servidores, atividade que por sinal envolve redimensionamento de imagem, correção de orientação, transformação para binário e então transformação desse binário para uma entidade na base 64.
O vídeo ficou um pouco longo, pois apesar de pouco codificar nele mostrei os passos necessários para se pegar a imagem do dispositivo (do próprio SDCard ou tirando a foto pela camera mesmo), alterar o tamanho dela, verificar se a orientação da imagem está correta, caso não esteja, corrigi-la. Então pegar o tipo mime da imagem (PNG, JPEG, GIF), salvar esses dados no objeto e prepará-lo para ser enviado para o servidor. Além de mostrar a codificação necessária no PHP para pegar a imagem em Base64, decodificar e então salvar um arquivo binário para criar a imagem no servidor. Mas enfim se sua dificuldade era enviar o Bitmap para uma servidor PHP o vídeo pode lhe ajudar a fazer isso. Fique ligado no uso da class Base64 que não necessita de seu entendimento por completo, basta saber que no caso do vídeo ela transformará nosso array de bytes em uma entidade na base 64. Sem mais delongas vou deixa-lo assistir ao vídeo.
O link para download do projeto se encontra logo abaixo no post incluindo o código PHP que salva os dados no servidor.
Segue links de alguns conteúdos que podem lhe ajudar a entender melhor esse exemplo:
Enviando e Recebendo Dados Entre Activities em Android
Página da classe Bitmap na sessão do método createBitmap() no site oficial do Android
Página da classe Matrix no site oficial do Android
Página da classe ExifInterface no site oficial do Android
Página do projeto Base64
Obtendo e Apresentando Rotas no OpenStreetMap AndroidAndroid
MarkerInfoWindow no OpenStreetMap AndroidAndroid
formulário android - envio de bitmap ao servidor - bitmap no form android
Comentários Blog (44)
Thiago Melo (1) (0)
Cara gostaria de uma ajuda.
Estou tentando salvar uma imagem em um diretório do Hostinger, porém não estou conseguindo faze-lo.
Na verdade estou criando um app (android) que irá enviar uma imagem para uma script php e esse script terá que salvar a imagem em um diretório do meu servidor Hostinger e a URL da imagem no banco de dados.
Já tentei de todas as formas (Base64, Retrofit) e não consegui.
Certamente estarei fazendo alguma coisa de errado. Poderia me ajudar nesse caso?
Sou novato em dev e estou estudando.
Vc já tentou das duas formas que eu poderia lhe indicar, base64 e Retrofit. Minha dúvida é se a imagem ao menos está chegando no backend Web, está? A versão do Retrofit para envio de imagem que vc utilizou foi a mesma que utilize aqui (http://www.thiengo.com.br/library-retrofit-2-no-android ). Abraço
Israel Hudson (1) (0)
Cara quando eu passo para o meu projeto esses pacotes não importam
Fala Israel, blz?
Mts dessas classes não mais estão disponíveis.
Utilize o Retrofit 2.0 (http://www.thiengo.com.br/library-retrofit-2-no-android ). Abraço
Poxa pensei que era ensinando a mesma coisa desse post porem usando android studio. Estou em um projeto que tenho que fazer examente o que esse seu post faz, com a diferença de ser 4 imgs. Vc poderia fazer um mais atualizado pq esse que vc me indicou não é a mesma coisa... abs :v
Israel, com o retrofit vc consegue enviar imagens de uma maneira até mais tranquila. Código similar ao vídeo desse post será difícil, pois muitas das entidades utilizadas aqui não mais estão disponíveis no Android. Abraço
Rogerio (1) (0)
Parabéns pelo belo trabalho, Thiengo.
Fiz a implementação e deu tudo certo.
Estou enviando do celular para o servidor PHP uma imagem tipo jpg, porém perde muita a qualidade da imagem.
As fotos são de documentos que não são coloridos, somente preto e branco.
Sabe algo a fazer?
Fala Rogerio, blz?
Quando utilizei esse algoritmo tb tive problemas algumas vezes, infelizmente o envio de imagens do Java para um servidor Web não é tão trivial como em PHP. Dê uma olhada nesse tuto (http://www.androidhive.info/2014/12/android-uploading-camera-image-video-to-server-with-progress-bar/ ), pelo menos na parte de uso do AndroidMultiPartEntity, pois aparentemente essa é a melhor maneira de envio. Dê uma olhada nessa lib tb (https://android-arsenal.com/details/1/2161 ). Abraço
Carlos Malta (2) (0)
Bom dia Thiengo. Parabéns pelo seu trabalho e fico grato por vc disponibilizar seu conhecimento que tem me ajudado bastante. Tenho muita dificuldade na programação mas estou aqui na luta pra aprender. Assisti essa video aula e consegui colocar pra rodar perfeitamente, porem gostaria de saber como selecionar e enviar mais de uma imagem ao mesmo tempo, se possivel mostra-las na tela pelo Galley e depois envia-las para o servidor PHP juntamente com o formulario. Se tiver algum video que possa me ajudar ficarei muito grato. Desde ja agradeço!
Fala Carlos Malta, blz?
Para o pick de multiplas imagens, veja essa resposta do stackoverflow (http://stackoverflow.com/a/27376429/2578331 ), pode ser que lhe ajude. Para enviar as várias imagens selecionadas, recomendo que envie primeiro o form sem dados binários (imagens, áudios, ...) e logo depois retorne o id do registro gerado para esses dados no banco de dados remoto. Depois de ter obtido o id comece a enviar as imagens para o servidor Web, porém no background, dentro de um Service, pois assim não vai bloquear a tela do user com um ProgressBar interminável devido ao envio de imagens (conteúdo pesado) no form. Abraço
Zé (1) (0)
Primeiramente parabéns pelo trabalho. Coloquei pra rodar e funcionou perfeitamente no android 2.3.7, upou as imagens e tudo, mas se eu rodar no android L eu só consigo fazer upload tirando foto. Quando tento fazer upload pela galeria ele chega abrir a galeria, daí quando seleciona a imagem dá erro e fecha o app.
Fiz uns Log.d() no código pra ver até onde ele estava indo e onde dava erro. Quando tentei dar uns Log.d() nessa "imgString" ele dava erro... deve estar aí o problema, mas não sei como resolver
No logcat aparece o seguinte:
http://pastebin.com/Fdk8jfMY
Dê uma olhada nesse link (http://stackoverflow.com/questions/27038051/pick-photo-from-gallery-in-android-5-0 ), veja a primeira resposta, porém antes leia a dúvida e o finalzinho dela dê uma atenção especial, pois é a informação do porquê do problema. Se essa solução passar, porém somente para o Android 5 e superior, utilize o Build.VERSIONS.SDK_INT, para definir qual Pick_Photo script utilizar de acordo com a versão do Android em uso. Abraço
Ronaldo Marcos (1) (0)
Boa tarde Thiengo, parabéns e obrigado pelo compartilhamento dos seus conhecimentos... Notei que num aplicativo que fiz enviando também imagens, quando a orientação do celular está ligada, depois da foto tirada ou mesmo dela escolhida via cartão, se eu giro o celular eu a perco, some do imageview e também não é enviada... Outra coisa, já tentou enviar vídeos usando o Base64? Obrigado.
Ronaldo (1) (0)
Quanto a orientação achei na documentação do Android que é próprio dele recriar a atividade quando gira, e que é necessário nesse caso armazenar e recuperar... Alguns casos é até melhor (como eu fiz) bloquear para não girar (da menos trabalho) rs
Realmente se não utilizar ou um SaveInstanceState (http://www.thiengo.com.br/otimizando-sua-app-android-com-onsaveinstancestate , http://www.thiengo.com.br/onsaveinstancestate-bitmap-e-serializable-no-android-correcao ), ou um configChanges em sua Activity (http://www.thiengo.com.br/entendendo-e-utilizando-o-configchanges-no-android ), ou um ApplicationClass (http://www.thiengo.com.br/application-class-no-android-entendendo-e-utilizando ) estendida vc não consegue continuar com o ImageView, na verdade vc não consegue ficar com nenhum dos objetos já criados se não utilizar algumas dessas técnicas citadas a cima, pois toda a Activity é reconstruida quando vc muda a orientação do aparelho e a APP não tem uma orientação travada via AndroidManifest (portrait ou landscape, que não recomendo a trava, pois há usuários que gostam de consumir o conteúdo da APP em orientação diferente da escolhida como trava). O onSaveInstanceState() pode ser uma boa escolha.
Esse script é bom, mas tive alguns problemas quando enviava imagens em conexões fracas, as vezes salvava a imagem pela metade... bad job! Não tentei enviar vídeos com ela... hj estou estudando mais Java para poder trabalhar melhor com bytes (Bitmap, ...) e Thread, pois para mim essas são as partes que mais dão problemas no Android e que mais podem deixar sua APP eficiente se souber trabalhar com elas (além dos layouts XML serem bem construidos), principalmente quando vc quer enviar algo como vídeo para um servidor Web, tem várias libs que ajudam a buscar, porém a enviar não conheço uma. Assim que desenvolver um script show de bola para envio eu coloco aqui no blog. Abraço
Ronaldo (0) (0)
Ola Thiango, tudo blz? Cara fiz tudo direitinho como vc falou no video mas esse Base64 não esta funcionando. Tudo funciona direitinho ele até esta salvando as imagens no diretório que eu criei em meu servidor mas eu não consigo visualizar as mesmas sempre que eu clico pra visualizar a imagem aparece essa mensagem "O windows Photo não pode abrir esta imagem por que o arquivo parece esta danificado, corrompido ou é muito grande". Eu não acredito que seja por causa do tamanho pois as imagens não passam de 80KB, então será algum problema no Base64? o que será que eu estou fazendo errado? lembrando que ele esta colocando as imagens no diretorio e tem até tamanho como eu falei, mas eu não consigo visualiza-las. Me ajude por favor. Abraço.
Fala Gustavo, blz sim.
Está colocando a imagem com o formato que ela era no APP (jpeg, png, gif, ...)? Mt provavelmente esse é o problema, pois como falo no vídeo, além do String base64 que enviamos temos de enviar tb em outra variavel post o formato real da imagem para realizarmos a conversão correta no server. Ve se está fazendo isso. Abraço
Opa Thiengo, dei mais uma analisada aqui e sim cara estou fazendo direitinho pegando o tipo mime e enviando separado da imagem msm assim não esta funcionando, da uma olhada aqui em meu codogo php e ve se estou fazendo algo errado.
if (isset($_REQUEST['image']))
$binaryImage = base64_decode($_REQUEST['image']);
$mimeImage = $_REQUEST['mime'];
//DEFINIÇÕES DA MUSICA
//$pasta = 'Musicas';
$extencoes = array('png', 'jpg');
if (!in_array($mimeImage, $extencoes))
{ // SE O TIPO MIME N FOR IGUAL AOS TIPOS PERMITIDOS NO NOSSO ARRAY DE EXTEÇÃOES....
echo "formato invalido, apenas jpg ou png";
$imageName = 'image-'.uniqid().'.'.$mimeImage;
$file = fopen('./Images/'.$imageName, 'wb');
fwrite($file, $binaryImage);
$sqlimage = "UPDATE `users` SET `images` = '".$imageName."' WHERE `username` = '".$username."' ";
if($db->query($sqlimage)){
else // SE O NOSSO PRIMEIRO SQL, NÃO DER CERTO $out RECEBE FAILED
É isso ja tentei de tudo mas n consigo descobrir o erro, se poder me ajude por favor. Abraço
Aparentemente está ok o código. Vc está utilizando $_RESQUEST[...], se não me engano $_REQUEST está depreciado, utilize $_POST[...]. Faça um testes antes, salve o nome da imagem e o conteúdo $binaryImage dentro de um arquivo txt para ver se os dados estão realmente chegando ao servidor. Se possível verifique as propriedades do arquivo gerado para ver se está como imagem mesmo e com conteúdo não igual a 0 bytes. Abraço
Sim cara eu tentei com o $_POST e não funcionou as outras coisas como nome e e-mail estão vindo direitinho só não a imagem, verifique as propriedades como vc falou e aparentemente sim esta vindo como uma imagem não está com 0 bytes a unica diferença que eu notei é que ele não ta me dando as dimensões as imagens que estão vindo pelo o seu codigo vem com as dimensões 300 x 300 ja as do meu codigo não estão vindo com as dimensões e no meu código java eu estou fazendo igualzinho como vc fez para alterar as dimensões da imagem. Será que isso tem alguma coisa haver com esse erro?
Gustavo, faça o seguinte teste se possível, envie uma imagem pequena em bytes e não altere as dimensões, só para ver se o problema está nessa parte do script. Ai volte aqui para falar do resultado. Abraço
Gustavo (2) (0)
Nada cara, continuou a mesma coisa o problema não é esse não mas eu fiz uma coisinha aqui , testei o meu codigo java no seu php e funcionou perfeitamente o problema ta no meu script php mesmo, por enquanto eu vou ficar usando o seu codigo que ta perfeito mas eu vou continuar estudando aqui o que que esta acontecendo com o meu código que aparentemente não tem nada de errado ai quando eu descobrir o qual foi o erro eu volto aqui pra te falar. De qualquer jeito obrigado seu blog tem me ajudado bastante vc é fera. Abraço cara.
José Monteiro (0) (0)
Olá Thiengo tudo na paz? sera que poderia me da uma ajuda?
Quado tiro a foto salva no SdCard corretamente porém não mostra no imageView. No "onActivityResult" a "Intent data" esta chegando null sabe o que pode ser?
desde já agradeço a atenção =D
Obs.: estou testando diretamente no aparelho.
Fala José, tudo na paz sim
Como vc que salvou no SDCard vc não precisa de dados do Intent retornado, vc pode acessar a foto direto pelo path que vc a gravou e então carrega-la como bitmap e coloca-la no ImageView. Abraço
Hemerson Silva (0) (0)
primeiramente parabéns pelo blog,está sendo muito útil no meu aprendizado.
Gostaria de saber como habilitar a função de recorte na imagem.
Fala Hemerson, blz?
Não tentei cortar bitmap direto no Android ainda, mas encontrei duas discussões sobre esse assunto no StackOverflow e aparentemente eles tem a solução na primeira resposta de cada discussão, segue os links, de repente ajuda:
http://stackoverflow.com/questions/18232034/how-can-i-crop-a-bitmap-for-imageview
http://stackoverflow.com/questions/15789049/crop-a-bitmap-image
Fala Thiengo, deu certo.
Francisco Pereira (0) (0)
no seu exemplo ele grava os dados da imagem em txt, como eu faria pra salvar no banco mysql o meu atributo é um varchar.
Fala Francisco, blz? Vc grava a imagem em um diretório de seu servidor (mostrei isso no vídeo) e o nome da imagem ao invés de gravar no txt vc grava no MySQL (estou assumindo que vc manja de MySQL, certo?), depois para acessar vc envia somente o nome da imagem com o respectivo endereço de seu dominio na Web com o endereço do diretório onde se encontra a imagem... no Android vc concatena todos os endereços incluindo o nome da imagem (com o mime type dela no final - jpg, png, gif) e com um ImageLoader vc pode baixar a imagem de seu Servidor na Web para algum ImageView ou algo do genero... essa é uma forma de fazer. Abraço
Francisco Pereira (1) (0)
assistir novamente o vídeo e identifiquei onde estava errando.
Fala Thiengo eu queria enviar uma imagem para um banco de dados MySQL seria da mesma maneira q enviar para um servidor PHP?
Bom, essa é uma maneira, existem outras maneiras. O que precisa ver que o script envia a imagem para o Servidor Web, pois o Android mesmo não sabe o que está no backend do servidor, ele apenas faz a imagem virar uma String base64 e envia. Mas vc esta guardando a imagem (byte) dentro do MySQL (tipo BLOB)? Ou está guardando o caminho da imagem no MySQL e a imagem em algum diretório do servidor (que considero a melhor opção)? De qualquer forma vc precisará de uma linguagem backend (PHP, ou Java, ou...) pois o Android não comunica diretamente com um bd remoto. Abraço
Eu posso usar um servlet pra receber e enviar para o BD?
e eu to gravando em um servidor so o caminho
Não vejo problemas em utilizar um servlet em seu servidor para isso, mesmo tendo um minimo contato com o backend-server em Java, se não me engano já fiz isso, porém o contexto é com Ajax e não com Android, mas o funcionamento é o mesmo. Abraço
Rafael Fonseca (0) (0)
para enviar uma imagem sem exibir ela no aplicativo e necessário fazer o redimensionamento? Pois to querendo fazer essa parte ja no servidor onde fica mais facil pra mim.
Na verdade não é, mas a ideia é vc tentar já otimizar o tamanho da imagem ali mesmo no APP, pois de forma incoerente as cameras dos dispositivos de hj tendem a gerar imagens com um tamanho grande (em bytes) e a qualidade da conexão com a Web não é tão boa se não for uma WiFi, logo redimensionar a imagem é uma forma de diminuir esse tamanho em bytes, como tb retirar a qualidade da imagem tb é uma excelente escolha, pois se não me engano até 50% menos de qualidade o olho humano ainda não consegue perceber. Pegar a imagem e enviar sem nenhum tratamento pode ser mt pesado para o usuário até mesmo na conexão WiFi, pois alguns aparelhos têm camera HD. Abraço
Oi Thiengo tudo bom? tenho acompanhado todas as suas vídeo aulas e tenho aprendido muito com vc, estou estudando esse vídeo agora, mas só tem um probleminha, quando eu faço o download do projeto e importo no meu eclipse os arquivos .xml vem todos em branco! já tentei importar umas quatros vezes e o eclipse sempre me da esse erro
"[2014-08-18 20:31:40 - ExemploSendImageForPhp] Project has no target set. Edit the project properties to set one.
[2014-08-18 20:31:41 - ExemploSendImageForPhp] Project has no target set. Edit the project properties to set one.
[2014-08-18 20:32:15 - ExemploSendImageForPhp] Parser exception for /ExemploSendImageForPhp/AndroidManifest.xml: Fim prematuro do arquivo.
[2014-08-18 20:32:17 - ExemploSendImageForPhp] Parser exception for /ExemploSendImageForPhp/AndroidManifest.xml: Fim prematuro do arquivo."
Sabe dizer o que pode estar acontecendo? Desde já obrigado.
Então, se não me engano a solução (uma possível) é vc ir copiando e colocando na mão mesmo. Dei uma olhada no AndroidManifest.xml para entender esse "Fim prematuro" e não vi nada de anormal. Tente fazer assim copiando e colando para ver se vai. As vezes é bugueira da importação do Eclipse. Abraço
Valeu cara, eu acho q foi bug do eclipse mesmo, fiquei tentando aqui, apagando e importando de novo ate que de repente ele resolveu importar direito rs, mas valeu cara muito obrigado, seu blog é show de bola
Diego Melo (2) (0)
Parabéns pelo blog que sempre apresenta um ótimo conteúdo
Estou evoluindo no dev Android e sempre que tenho dúvidas dou uma passada por aqui e
como estou acompanhando a literaratura do Lecheta suas postagens sempre veem como um grande reforço e tem me ajudado muito.
Vlw Diego. Abraço
Tiago Winehouse (2) (0)
Agradeço por vc esta compartilhando a sua experiencia, Parabéns cara.. Tdos os dias assisti-o os seus videos..