Cómo crear archivos con Javascript

Cuando desarrollamos una aplicación web, muchas veces es necesario darle a los usuarios la posibilidad de exportar la información en un archivo que puedan descargar. Puede ser una copia de seguridad de los ajustes de la configuración de la aplicación, informes, u otra información que se genere dinámicamente.

La solución habitual a este problema sería tener un script a medida desarrollado para exportar lo que se desee a partir de una base de datos y después, generar un fichero. Sin embargo, como te probaremos en este artículo, hay otro modo.

Vamos a hacer un plugin de jQuery que, combinado con un simple script de php, puede generar cualquier tipo de archivo de texto, y habitarlo para su descarga. La descarga se iniciará desde el front end de Javascript proporcionándole únicamente el contenido, lo demás se lo dejaremos al plugin.

El HTML

Vamos a empezar como siempre, creando una página HTML simple con un área de texto y un botón de descarga, con el cual probaremos cómo funciona el plugin.

index.html

 

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />

        <!-- Our CSS stylesheet file -->
        <link rel="stylesheet" href="assets/css/styles.css" />

        <!--[if lt IE 9]>
          <script src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script>
        <![endif]-->
    </head>

    <body>

        <header>
            <h1>Generating Files with JavaScript</h1>
        </header>

        <form action="./" method="post">
            <textarea></textarea>
            <a href="#" class="blueButton" id="download">Download</a>
        </form>

        <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.0/jquery.min.js"></script>
        <script src="assets/js/jquery.generateFile.js"></script>
        <script src="assets/js/script.js"></script>

    </body>
</html>

Hemos usado HTML5 para crear dicha plantilla, por lo cual verás que hemos utilizado algunos tags del estándar. Para que funcione en IE, tendremos que incluir el script que permite la ejecución de HTML5 en la sección head.
Antes de que cerrar la etiqueta body, agregaremos la librería jQuery, el GenerateFile que estaremos escribiendo en un momento, y el archivo script.js que recibirá los eventos y desencadenará las descargas de los archivos.

El PHP

Como probablemente sabes, generar archivos no es posible solo con Javascript. De todas maneras, existen diferentes soluciones (muchas de ellas relacionadas con Flash), pero usar un script de PHP genérico en el backend proporciona un mejor control y una mayor facilidad de uso (por no decir que esto también funciona en los principales navegadores).

Puedes ver el contenido del script genérico de PHP a continuación:

download.php

if(empty($_POST['filename']) || empty($_POST['content'])){
        exit;
}

// Sanitizing the filename:
$filename = preg_replace('/[^a-z0-9-_.]/i','',$_POST['filename']);

// Outputting headers:
header("Cache-Control: ");
header("Content-type: text/plain");
header('Content-Disposition: attachment; filename="'.$filename.'"');

echo $_POST['content'];

Lo que este script de PHP hace es, simplemente, añadir algunos headers justo arriba de la declaración del echo. El plugin que estamos construyendo debe pasar dos parámetros en la solicitud POST: el nombre del archivo y elcontenido. El script imprimirá el contenido del archivo, mientras que las tres cabeceras obligarán a la caja de descargas de archivos a aparecer.

Para utilizar el plugin necesitas subir este archivo en algún lugar de tu servidor y pasarle su URL al plugin que desarrollaremos a continuación.

El jQuery

Como hemos visto en la sección anterior, nuestro plugin tiene que emitir una petición POST a download.php. Por lo general esto lo haríamos habitualmente mediante el uso de AJAX. Sin embargo, hay un inconveniente en la utilización de este método: esto no habilita que aparezca el cuadro de descargas.

Así que lo que necesitamos es un poco más de la vieja escuela. Crearemos dinámicamente un iframe oculto y crearemos un formulario en el mismo, al cual después haremos submit via POST. El atributo de action del formulario debe redirigir a download.php, por lo que el cuadro de diálogo de descarga de archivos aparecerá exactamente como lo necesitamos.

Ahora vamos a ver el código jQuery que hace esto posible:

(function($){

    // Creating a jQuery plugin:

    $.generateFile = function(options){

        options = options || {};

        if(!options.script || !options.filename || !options.content){
            throw new Error("Please enter all the required config options!");
        }

        // Creating a 1 by 1 px invisible iframe:

        var iframe = $('<iframe>',{
            width:1,
            height:1,
            frameborder:0,
            css:{
                display:'none'
            }
        }).appendTo('body');

        var formHTML = '<form action="" method="post">'+
            '<input type="hidden" name="filename" />'+
            '<input type="hidden" name="content" />'+
            '</form>';

        // Giving IE a chance to build the DOM in
        // the iframe with a short timeout:

        setTimeout(function(){

            // The body element of the iframe document:

            var body = (iframe.prop('contentDocument') !== undefined) ?
                            iframe.prop('contentDocument').body :
                            iframe.prop('document').body;    // IE

            body = $(body);

            // Adding the form to the body:
            body.html(formHTML);

            var form = body.find('form');

            form.attr('action',options.script);
            form.find('input[name=filename]').val(options.filename);
            form.find('input[name=content]').val(options.content);

            // Submitting the form to download.php. This will
            // cause the file download dialog box to appear.

            form.submit();
        },50);
    };

})(jQuery);

En menos de 50 líneas, el snippet anterior hace lo que necesitamos. Crea un iframe oculto con un formulario en su interior.

Fíjate en la función setTimeout(). Sin ella no podremos acceder al iframe en Internet Explorer. De esta manera, estamos dando tiempo para construir el DOM y ponerlo a disposición nuestra.

Y así es como se utiliza este plugin:

$(document).ready(function(){

        $('#download').click(function(e){

                $.generateFile({
                        filename        : 'export.txt',
                        content         : $('textarea').val(),
                        script          : 'download.php'
                });

                e.preventDefault();
        });

        $('#downloadPage').click(function(e){

                $.generateFile({
                        filename        : 'page.html',
                        content         : $('html').html(),
                        script          : 'download.php'
                });

                e.preventDefault();
        });

});

Cuando llamamos a $.generateFile necesitamos pasarle el nombre del fichero (procura que sea lo bastante descriptivo), el contenido y la ruta a download.php. Como puedes ver en el ejemplo de arriba, se puede generar cualquier tipo de archivo, sin importar su contenido ni su tamaño.

COMPARTE ESTE ARTÍCULO

COMPARTIR EN FACEBOOK
COMPARTIR EN TWITTER
COMPARTIR EN LINKEDIN
COMPARTIR EN WHATSAPP