Hoy vamos a preparar un pequeño tutorial sobre como hacer una foto con la cámara del móvil y subirla a un servidor, en este caso voy a usar un servidor PHP y aportaré el código, pero podríais hacerlo en cualquier otro si tenéis experiencia.
Empezamos creando el proyecto:
create subirImagen es.phonegap.subirimagen subirImagen
vamos al directorio del proyecto, añadimos los plugins de cámara y file transfer y las plataformas ios y android (yo voy a trabajar con iOS, pero el código es igual para ambas)
cd subirImagen cordova plugin add cordova-plugin-camera cordova plugin add cordova-plugin-file-transfer cordova platform add ios android
Para simplificar, vamos a trabajar diréctamente en el index.html, así que eliminamos las carpetas css y js que hay dentro de la carpeta www y abrimos el index.html y lo dejamos así:
<!DOCTYPE html> <html> <head> <meta name="viewport" content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width"> <title>Subir imagen</title> <script> </script> </head> <body> <div class="app"> <h1>Apache Cordova</h1> </div> <script type="text/javascript" src="cordova.js"></script> </body> </html>
Parte 1: Hacer la foto
Dentro del div con clase app añadimos un botón que llamará a la función de hacer la foto, y una etiqueta img para mostrar la imagen que hemos hecho:
<input type="button" onclick="hacerFoto();" value="Hacer Foto"> <img id="fotoLocal" src="" width="100px" height="100px">
Y dentro de la etiqueta script definimos la función hacerFoto
function hacerFoto(){ navigator.camera.getPicture(onSuccess, onFail, { quality: 50, destinationType: Camera.DestinationType.FILE_URI }); } function onSuccess(imageURI) { var image = document.getElementById('fotoLocal'); image.src = imageURI; } function onFail(message) { alert('Failed because: ' + message); }
Parte 2: subir la foto al servidor
Vamos a añadir otra etiqueta img más para mostrar la imagen una vez subida al servidor
<img id="fotoServidor" src="" width="100px" height="100px">
Y definimos la función subirImagen que llamaremos en el success de la cámara pasando la ruta de la imagen
function subirImagen(fileURL) { var options = new FileUploadOptions(); options.fileKey = "imagen"; options.fileName = fileURL.substr(fileURL.lastIndexOf('/') + 1); var ft = new FileTransfer(); ft.upload(fileURL, encodeURI("http://jcesar.16mb.com/upload/upload.php"), uploadSuccess, uploadFail, options); } function uploadSuccess(r) { alert("Code = " + r.responseCode+" Response = " + r.response+" Sent = " + r.bytesSent); } function uploadFail(error) { alert("An error has occurred: Code = " + error.code+ " upload error source " + error.source+" upload error target " + error.target); }
Ya estaría todo, simplemente hacemos que en al recibir el success de la subida, cogemos la url que nos devuelve y se lo asignamos a nuestra segunda img. Nuestro index.html debería haber quedado así:
<!DOCTYPE html> <html> <head> <meta name="viewport" content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width"> <title>Subir imagen</title> <script> function hacerFoto(){ navigator.camera.getPicture(onSuccess, onFail, { quality: 50, destinationType: Camera.DestinationType.FILE_URI }); } function onSuccess(imageURI) { var image = document.getElementById('fotoLocal'); image.src = imageURI; subirImagen(imageURI) } function onFail(message) { alert('Failed because: ' + message); } function subirImagen(fileURL) { var options = new FileUploadOptions(); options.fileKey = "imagen"; options.fileName = fileURL.substr(fileURL.lastIndexOf('/') + 1); var ft = new FileTransfer(); ft.upload(fileURL, encodeURI("http://jcesar.16mb.com/upload/upload.php"), uploadSuccess, uploadFail, options); } function uploadSuccess(r) { alert("Code = " + r.responseCode+" Response = " + r.response+" Sent = " + r.bytesSent); var image = document.getElementById('fotoServidor'); image.src = r.response; } function uploadFail(error) { alert("An error has occurred: Code = " + error.code+ " upload error source " + error.source+" upload error target " + error.target); } </script> </head> <body> <div class="app"> <h1>Apache Cordova</h1> <input type="button" onclick="hacerFoto();" value="Hacer Foto"> <img id="fotoLocal" src="" width="100px" height="100px"> <img id="fotoServidor" src="" width="100px" height="100px"> </div> <script type="text/javascript" src="cordova.js"></script> </body> </html>
Parte 3 y final
Ya solo queda que nuestro servidor pueda recibir la imagen, para ello, como dije al principio, vamos a usar PHP. Para la prueba he usado un servidor gratuito de hostinger, pero no lo recomiendo para producción, podeis usar esa misma url para hacer pruebas o crearos uno vosotros mismos.
Este es el código PHP que se necesitaría:
<?php $target_dir = "upload/"; $target_file = $target_dir . basename($_FILES["imagen"]["name"]); move_uploaded_file($_FILES["imagen"]["tmp_name"], "./" . $_FILES["imagen"]["name"]); echo "http://" . $_SERVER['SERVER_NAME'] . "/" . $target_file; ?>
Lo único que hace es coger la imagen subida y moverla (con move_uploade_file) de la carpeta temporal de subidas a la carpeta que nosotros queremos, en este caso la misma donde está el upload.php, y una vez subida, devuelve la ruta de la imagen donde se ha almacenado para que se la asignemos al src de nuestra imagen.
Fijaos en $_FILES[«imagen»], imagen es el nombre que pusimos en options.filekey, si cambiasemos ese nombre habría que cambiarlo también en el .php.
Espero que os haya gustado, y si tenéis algún problema no dudeis en comentar.
Gracias por el tutorial. Me funciona hasta donde toma la foto, pero no sube la imagen ni me da un mensaje de error. La pagina upload.php la hospedo en un servidor Windows 2.008 Server.
Probaste en iOS o android? Tienes el upload.php online para que pueda probar a ver si me puedo conectar?
Muy buen tuturial muchas graciassss!
Buen día
Tengo el mismo problema, la app no muestra ningùn mensaje de error, pero no carga ni muestra la imágen en el servidor,
tengo montado un servidor local en debian 8 php 5.6
En que dispositivo estás probando? versiones de cordova CLI y de la plataforma en la que pruebas? versión del plugin? has intentado la depuración remota a ver si te sale algún error? porque es muy raro que no te salga ningún error en los callbacks si está fallando
Estimados…solucionaron la carga de la imagen?
A mi la variable imageURI me sale como undifined, me podrias ayudar por favor, solo que yo lo estoy haciendo en dreamweaver
Donde lo estás probando? si te sale undefined puede ser algún problema con el plugin de la cámara
Excelente tutorial, muy bien explicado. Me ha sido de gran ayuda, muchas gracias por compartir tus conocimientos. Una pregunta, si quisiera enviar al server un formulario con 4 fotografías o menos, ¿qué me recomendarías?.
Lo de subir varias es complejo/imposible porque el file transfer solo las puede subir de una en una
Puedes subir varias, pero por separado, y esperar a que se hayan subido todas usando promises
http://www.raymondcamden.com/2015/08/10/processing-multiple-simultaneous-uploads-with-cordova
Gran tuto… pero me sale esto bro….
Alert
An error has ocurred:code=1 upload error source file:///storage/emulated/0/Android/data/com.example.subirimagen/cache/14623
72331884.jpg upload errortarget http://192.168.43.139/wwwPruebas/funcionesPHP/upload.php
ya lo resolvi amigo.. la ruta no estaba correcta… gracias ..
Hola buenos dias, te comento hace algunos dias cree un proyecto con el cordova que instale en eclipse y me resulto un proyecto con una version de cordova muy antiguo, desarrolle una app y funciona muy bien, el problema esta al momento de colgarlo en google, que no acepta versionces de cordova intefiores a 3.5.0 o 4.1.0 … despues cree un nuevo proyecto pero desde la terminal de Ubuntu alli me salio un proyecto con version de cordova 5.1.1 suficiente para aprobar la restriccion, luego agregue los plugins como se indican en varios tutoriales y no tuve ningun problema, la dificultar es que a pesar de agregar los plugins estos no se enlazan de forma correcta con el codigo que uso para lebantar mi camara, detectar mi geolocalizacion o conectarme a la red, no esta reconociendo ningun plugin, algo que en la version antigua de mi proyecto si funcionaba, nose si estoy omitiendo algo o estoy haciendo algo mal, el codigo que uso en mi proyecto es el mismo que expones en este post, nose por que ahora en la version mas reciente de cordova, esos perifericos no funcionan, espero me puedas ayudar, gracias de antemano, saludos.
Intenta empezar desde 0 siguiendo el tutorial desde el principio, porque se explica como crear el proyecto con el CLI y como añadir los plugins necesarios.
ola amigo la verdad es que sube la imagen pero codificada como la descodificas en php osea una imagen que se llama photo.png me la guarda de esta manera acc%3D1%3Bdoc%3D10133 como descodificas esta imagen ??
Hola. El problema en esos casos es el plugin camera que no devuelve el nombre correcto. Estás usando la última versión del plugin?
Si usas la última versión y sigues con el problema, puedes cambiar varias cosas para poner tu el nombre que quieras.
Si cambias esta linea del javascript
options.fileName = fileURL.substr(fileURL.lastIndexOf(‘/’) + 1);
por
options.fileName = «ElNombreQueTuQuieras.png»; puedes mandar ya el nombre que tu quieras desde la app, pero hay el problema de que la imagen que estés subiendo no sea un .png
Otra opción sería poner el nombre que tu quieras en el servidor, que ahí con PHP si podrás saber el mime type de la imagen y con ello poner tu la extensión que corresponda.
Pero también cuando monto una imagen desde la galería me la sube de esa manera
Te estoy diciendo que es el plugin camera el que hace eso, cuando es de la galería a veces no obtiene el nombre original de la imagen y saca esas cosas raras.
Yo utilizo ionic y el plugin es de ng-cordova creo que el plugin esta actualizado verificaré de nuevo sugieres que php haga un correo condiciones con el mimetype gracias bro por tus respuesta
Hola, puedes ayudarme por favor he buscado como abrir imagénes desde la galeria pero siempre termina abriendo la cámara, por favor indicame que debería cambiar para escoger la imagen desde la galeria, aquí la función como está actualmente.
navigator.camera.getPicture(onSuccess, onFail, { quality: 50, destinationType: Camera.DestinationType.DATA_URL});
function onSuccess(imageURI) {
var image = document.getElementById(‘fotoLocal’);
image.src = imageURI;
subirImagen(imageURI)
}
function onFail(message) {
alert(‘Failed because: ‘ + message);
}
Gracias!!!!
Buenas. Para usar la galería tienes que pasar la opción sourceType Camera.PictureSourceType.PHOTOLIBRARY
sourceType: Camera.PictureSourceType.PHOTOLIBRARY
Ah, y para que tu código funcione tienes que usar Camera.DestinationType.FILE_URI en vez de DATA_URL
Hola.
Muy bueno el tutorial . Claro y bien explicado.
Tengo un problema enla subida al servidor que me lanza el error Code 1 upload error source file…..
Alguna pista?
Gracias
Hola.
Estaba probando en un terminal con la Android 6.0.
He probado en el emulador y sí funciona.
Puede ser cosa de permisos?
Creo recordar que en el mismo terminal, es decir con el mismo Android, unas pruebas que hice con el tutorial me funcionaron.
Si usas las últimas versiones de los plugins no deberías tener problemas de permisos porque todos están actualizados para funcionar bien con los permisos de Android 6.
Hola buen día, tengo una duda, he ejecutado el código y mi archivo upload.php esta en un proyecto local dentro de htdocs, por lo que la ruta queda algo asi
ft.upload(Archivo,»http://ipdemiPc/zizicom/trizApi/images/upload.php», win, fail, options);
Y funciona, es decir, me sube la imagen, todo bien.
El detalle viene cuando ya tengo el proyecto en un hosting real, es decir, ya no está en mi PC
ft.upload(Archivo,»http://urlsitioweb/zizicom/trizApi/images/upload.php», win, fail, options);
me aparece en la ubicación un archivo con este mensaje:
[18-Nov-2016 03:50:43 UTC] PHP Notice: Undefined index: file in /home/zizicom/public_html/trizApi/images/server.php on line 2
¿tengo que configurar en el servidor alguna especie de permisos de escritura en el directorio donde quiero que se guarden las imagenes?
Pero estás usando el mismo código tanto en el javascript como en el PHP?
Porque lo que te está diciendo es que «file» no está definido, pero en mi ejemplo he usado «imagen», no «file» $_FILES[«imagen»][«name»].
El primer valor («imagen» en mi ejemplo), tiene que coincidir con el valor que uses en options.fileKey.
También, si estás usando la versión 1.6.x del plugin, prueba con la versión 1.5.1, que parece que hay algunos errores en la versión 1.6.x
Si, he cambiado el nombre, en la aplicación está:
options.fileKey = «file»;
y en el php:
$file = $_FILES[«file»][«name»];
En cuanto al plugin:
Entonces seguramente sera que el hosting no tiene activada la subida de ficheros.
Ejecuta phpinfo() en algun script para comprobarlo
es la version 1.5.0
Tengo una aplicación desarrollada en PHP que requiere la activación de la camara y tomar una foto pero en sistemas Android, solo me falta la toma de foto pero este código creo que no es funcional para el objetivo, alguien puede sarme alguna idea? por favor contactenme a m i correo faltamiranooliva@gmail.com agradeceré su apoyo.
Has probado el código y no te funciona en Android?
Hola, vi tu tutorial y me parecio muy interesante, estoy tratando de subir una imagen a un web server, pero no lo tengo con PHP, el código para subir la imagen valdría si cambio la ruta a la de mi servidor, o tendria que hacerlo de otra manera? Muchas gracias.
Si, con cambiar la ruta te debería valer, siempre y cuando tu servidor esté esperando la key «imagen»
Hola, me encontre con tu tutorial buscando la manera de hacer esto mismo pero con Ionic 3 y subirlo mediante php a una bd mysql, ya pude hacer uso de la camara con ionic, se me complica la transferencia, y definicion de carpeta donde guardar la imagen, tendras algun ejemplo de eso?
No entiendo muy bien que es lo que se te complica
Hola:
Con
No se abre la cámara.
SI pongo
Si que se abre, hago la foto, pero no se guarda en el servidor.
Puedes ayudarme?
Gracias.
Me podrías indicar cómo enviar la foto te acabas de tomar hola foto de la galería así a un correo electrónico y que quede enviado no en la carpeta de salida pendiente
No es posible, el usuario siempre tiene que confirmar antes de enviar un SMS o email.
Lo que podrías hacer es que sea el servidor el que envíe la foto (con la función mail() si el servidor lo acepta), pero no usará el correo del usuario, usará lo que tengas configurado en el servidor para enviar correos.
tengo la duda de que iria en ($_SERVER) nombre del servidor e dominio alojado?
Es una variable de PHP, no tendrías que cambiar nada, el servidor PHP lo debería convertir en la url automáticamente
https://www.php.net/manual/en/reserved.variables.server.php