Android

12 fev, 2014

Tire fotos com um aplicativo phonegap/cordova e envie-as para o servidor

Publicidade

Recentemente, tenho trabalhado no projeto phonegap/cordova. O principal objetivo do projeto era tirar fotos com a câmera do dispositivo e enviá-las para o servidor. É um projeto apache cordova usando o plugin camera. De acordo com a documentação, podemos enviar imagens com o seguinte código javascript:

navigator.camera.getPicture(onSuccess, onFail, {
    quality: 100,
    destinationType: Camera.DestinationType.DATA_URL
});

function onSuccess(imageData) {
    // here we can upload imageData to the server
}

function onFail(message) {
    alert('Failed because: ' + message);
}

Como podemos ver, nosso plugin devolve uma versão codificada em base64 de nossa imagem, e podemos enviá-la ao servidor utilizando o JQuery, por exemplo.

function onSuccess(imageData) {
  $.post( "upload.php", {data: imageData}, function(data) {
    alert("Image uploaded!");
  });
}

O lado do servidor é trivial. Precisamos apenas ler a variável ‘data’ requisitada, realizar uma decodificação base64 e teremos a nossa imagem binária pronta para ser salva.

Testei com um smartphone Android antigo (com uma câmera não tão boa) e funciona, mas quando tentei usá-lo com um telefone Android melhor (com uma câmera de 8Mpx) ele ficou carregando e não funcionou. Depois de ler melhor a documentação, percebi que essa não é a melhor forma de enviar imagens para o servidor. Ela só funciona se a imagem é pequena. A base64 aumenta o tamanho da imagem e nosso dispositivo pode ter problemas para manipular a memória. Essa forma também é lenta como uma tartaruga.

A melhor maneira (aquela que funciona de fato) é, em vez de enviar imagens em base64 para o servidor, salvá-las dentro de uma pasta temporária no dispositivo e enviá-las usando o plugin de transferência de arquivos.

var pictureSource;   // picture source
var destinationType; // sets the format of returned value

document.addEventListener("deviceready", onDeviceReady, false);

function onDeviceReady() {
    pictureSource = navigator.camera.PictureSourceType;
    destinationType = navigator.camera.DestinationType;
}

function clearCache() {
    navigator.camera.cleanup();
}

var retries = 0;
function onCapturePhoto(fileURI) {
    var win = function (r) {
        clearCache();
        retries = 0;
        alert('Done!');
    }

    var fail = function (error) {
        if (retries == 0) {
            retries ++
            setTimeout(function() {
                onCapturePhoto(fileURI)
            }, 1000)
        } else {
            retries = 0;
            clearCache();
            alert('Ups. Something wrong happens!');
        }
    }

    var options = new FileUploadOptions();
    options.fileKey = "file";
    options.fileName = fileURI.substr(fileURI.lastIndexOf('/') + 1);
    options.mimeType = "image/jpeg";
    options.params = {}; // if we need to send parameters to the server request
    var ft = new FileTransfer();
    ft.upload(fileURI, encodeURI("http://host/upload"), win, fail, options);
}

function capturePhoto() {
    navigator.camera.getPicture(onCapturePhoto, onFail, {
        quality: 100,
        destinationType: destinationType.FILE_URI
    });
}

function onFail(message) {
    alert('Failed because: ' + message);
}

Eu percebi que às vezes isso falhava. Parece ser um bug no plugin do cordova (não tenho certeza); por causa disso, se você ler o meu código, pode ver que se pf.upload falhar eu tento novamente (apenas uma vez). Com esse pequeno truque, funciona que é uma beleza (e ainda é rápido).

A parte do servidor é bastante simples. Precisamos apenas manipular os arquivos enviados. Aqui está um exemplo minimalista em PHP:

<?php
move_uploaded_file($_FILES["file"]["tmp_name"], '/path/to/file');

E é só. Podemos fazer facilmente o upload de nossas fotos de nossos smartphones usando phonegap/cordova.

***

Artigo traduzido pela Redação iMasters, com autorização do autor. Publicado originalmente em http://gonzalo123.com/2013/10/28/taking-photos-with-a-phonegapcordova-application-and-uploading-them-to-the-server/