JavaScript & PHP: capturando y enviando imagen de la cámara

2021-11-25 - Categorías: General
Código fuente

Sencillo codekata en JavaScript y PHP para hacer una captura de la cámara, enviando luego mediante puro JavaScript la imagen a un script PHP que guardará la imagen en el servidor.

Este post es continuación sobre este otro sobre cómo capturar una imagen de la webcam con JavaScript añadiendo el envío y recepción al servidor.

El código fuente

A partir del fuente anterior, se puede añadir lo siguiente para convertir la imagen de la etiqueta HTML canvas en un objeto dataURL. Luego a su vez éste se convierte a blob con ayuda de comentarios de Stack Overflow de donde han compartido la función. Finalmente se envía en puro JavaScript y se recepciona grabando al mismo directorio.

El fuente en HTML y JavaScript

<!DOCTYPE html>
<html lang="es" dir="ltr">

<head>
    <meta charset="utf-8">
    <title>JnjSite.com: taking photo from camera</title>
</head>

<body>
    <h1>JnjSite.com: taking photo from camera</h1>
    <p id="errorTxt"></p>
    <div>
        <video id="theVideo" controls autoplay></video>
        <canvas id="theCanvas"></canvas>
    </div>
    <button id="btnCapture">Capture</button>
    <button id="btnDownloadImage">Download captured image</button>
    <button id="btnSendImageToServer" disabled>Send image to server</button>
    <script type="text/javascript">
        var videoWidth = 320;
        var videoHeight = 240;
        var videoTag = document.getElementById('theVideo');
        var canvasTag = document.getElementById('theCanvas');
        var btnCapture = document.getElementById("btnCapture");
        var btnDownloadImage = document.getElementById("btnDownloadImage");
        var btnSendImageToServer = document.getElementById("btnSendImageToServer");

        videoTag.setAttribute('width', videoWidth);
        videoTag.setAttribute('height', videoHeight);
        canvasTag.setAttribute('width', videoWidth);
        canvasTag.setAttribute('height', videoHeight);

        window.onload = () => {
            navigator.mediaDevices.getUserMedia({
                audio: true,
                video: {
                    width: videoWidth,
                    height: videoHeight
                }
            }).then(stream => {
                videoTag.srcObject = stream;
            }).catch(e => {
                document.getElementById('errorTxt').innerHTML = 'ERROR: ' + e.toString();
            });

            var canvasContext = canvasTag.getContext('2d');

            // Capture button..
            btnCapture.addEventListener("click", () => {
                canvasContext.drawImage(videoTag, 0, 0, videoWidth, videoHeight);
                btnSendImageToServer.removeAttribute("disabled");
            });

            // Download button..
            btnDownloadImage.addEventListener("click", () => {
                var link = document.createElement('a');
                link.download = 'capturedImage.png';
                link.href = canvasTag.toDataURL();
                link.click();
            });

            // Send image to server button..
            btnSendImageToServer.addEventListener("click", () => {
                var dataURL = theCanvas.toDataURL();
                var blob = dataURLtoBlob(dataURL);
                var data = new FormData();
                data.append("capturedImage", blob, "capturedImage.png");

                var xmlHttp = new XMLHttpRequest();
                xmlHttp.onreadystatechange = function () {
                    if (xmlHttp.readyState == 4 && xmlHttp.status == 200) {
                        alert(xmlHttp.responseText);
                    }
                }
                xmlHttp.open("post", "testingCam.php");
                xmlHttp.send(data);
            });

            // https://stackoverflow.com/questions/6850276
            function dataURLtoBlob(dataURL) {
                var arr = dataURL.split(','),
                    mime = arr[0].match(/:(.*?);/)[1],
                    bstr = atob(arr[1]),
                    n = bstr.length,
                    u8arr = new Uint8Array(n);
                while (n--) {
                    u8arr[n] = bstr.charCodeAt(n);
                }
                return new Blob([u8arr], {
                    type: mime
                });
            }
        };
    </script>
</body>

</html>

El fuente en PHP para recepcionar la imagen

<?php

move_uploaded_file($_FILES['capturedImage']['tmp_name'], "testingCam.png");

Cómo arrancarlo, probar los scripts

Se puede crear por ejemplo un fichero testingCam.html y testingCam.php, para luego lanzar desde línea de comandos:

php -S localhost:8000

..y acceder entonces a: http://localhost:8000/testingCam.html

4 respuestas a “JavaScript & PHP: capturando y enviando imagen de la cámara”

  1. Antonio Claros dice:

    Como puedo hacer lo siguiente

    1. Quiero que todo este codigo antes se abra desde un input (estaba pensando que se abra con un modal)
    2. Que capture la imagen luego se cierre el modal y guarde la imagen capturada en el mismo input

    Me dijieron que con python era mas rapido pero no se si me puedes ayudar
    gracias

    • Jnj dice:

      Buenos días Antonio.

      Primero que todo muchas gracias por dejar un comentario. Vas a necesitar varias cosas, te voy comentando todo por partes para que puedas ir investigando cada cosa y las programes:

      • Si quieres abrir modales en una web puedes hacer divs que se abran y cierren mediante JavaScript usando CSS por ejemplo, esto es lo más fácil. Otra alternativa para hacer modales, es usar por ejemplo Bootstrap como una de las soluciones fáciles, aquí más ayuda: https://getbootstrap.com/docs/4.0/components/modal/ Hay muchos más frameworks para hacer modales en el frontend como Angular, React, VueJS.. si te animas te sugiero Angular, pero inicialmente es más sencillo que lo construyas con HTML, CSS y JavaScript sin ningún framework como te indico al principio.
      • Para el proceso de captura y cierre del modal, es más de lo mismo, tendrás que usar JavaScript para darle el comportamiento que quieras en los clicks a los botones que quieras usar.
      • Para guardar el fichero en el servidor da igual PHP, que Python, Java.. o el lenguaje que quieras utilizar. Ya ves que en PHP es sólo una línea de código, con Python creo que serían más, con Java muchas más líneas seguro.. no creo que sea un problema de velocidad el guardar una imagen en el servidor, si no más bien de complejidad.

      Ánimo con ello, para cualquier cosa no dudes en consultar.

      Saludos.

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

 

© 2024 JnjSite.com - MIT license

Sitio hecho con WordPress, diseño y programación del tema por Jnj.