Icono del sitio Daniel Ruiz

Amazon S3, subida de ficheros simple y segura

Hola amigos!

Hoy vengo a ayudar a aquel que quiera implementar un sistema de subida de ficheros a Amazon S3 con el método drag&drop de HTML5.

  1. Para implementar la subida drag&drop de HTML5 usaremos la librería jquery.filedrop.js. Descargarla y poner en vuestra carpeta js… (así como jquery!)
  2. El bloque de html que contenga el control de subida de ficheros podrá ser algo asi:
    
    <div class="upload" id="uploader">
    
       <h3 class="icono-nube-upload-grande">Subiendo ficheros...</h3>
       <ul></ul>
       <div>
          <span>Arrastra y suelta </span>
       </div>
    </div>
  3. Un poquito de CSS:
    
    .upload{
        background-color: transparent;
        width: 100%;
        -webkit-box-sizing: border-box;
        padding: 1%;
        -moz-box-sizing: border-box;
        box-sizing: border-box;
        height: 145px;
        border-color: #cccccc;
        border-width: 7px;
        -moz-border-radius: 17px;
        -webkit-border-radius: 17px;
        border-radius: 17px;
        border-style: dashed;
        display: inline-block;
        position: relative;
    }
    h3{
        margin: 0;
        padding: 0;
    }
    .over{
        border-color: #333333;
    }
    

    El resultado… (algo así como…)

    Subiendo ficheros…

    Arrastra y suelta
  4. Comienza la magia! El script PHP que nos devolverá la URL de Amazon prefirmada y lista para hacer el PUT del fichero; deberéis tener a mano un bucket, la clave privada y pública de Amazon (AWSAccessKeyId y AWSSecretKey)… Si tenéis dudas sobre dónde se obtienen estos datos, preguntadme!
    
    //el nombre del bucket de Amazon al que quieres subir tus ficheros
    $bucket = 'mrvision22';
    //tiempo en el que va a expirar
    $expires = time() + 10000;
    //Este fichero lo podrá leer cualquiera (estos permisos se pueden modificar)
    $amzHeaders= "x-amz-acl:public-read";
    //El nombre del fichero que vamos a subir
    $filename = $_GET["filename"];
    $mimeType = "";
    //esta clave la tenemos que obtener de Amazon
    $amazonSecretKey = "xxxx";
    //Así como esta... es como la clave pública en una comunicación cifrada con certificado
    $AWSAccessKeyId = "xxxxx";
    
    //Se compone la cadena de la petición PUT al REST API de S3
    $stringToSign = "PUT\n\n{$mimeType}\n{$expires}\n{$amzHeaders}\n/{$bucket}/$filename";
    
    //Y se firma
    $hash = base64_encode(hash_hmac('sha1', $stringToSign, $amazonSecretKey, true));
    $sig = urlencode($hash);
    
    $url = urlencode(
        "https://{$bucket}.s3.amazonaws.com/{$filename}?AWSAccessKeyId={$AWSAccessKeyId}&Expires={$expires}&Signature={$sig}"
    );
    echo $url;
    
    
  5. Un breve inciso antes de proseguir… el Bucket de Amazon debe tener configurado el CORS (Cross-Origin Resource Sharing) para permitir el cross-scripting seguro: para el ejemplo permitimos cualquier conexión. Pensad que para que cualquier conexión de subida de ficheros es necesario las claves (y la privada no se la debéis de dar a nadie!)
  6. Y el javascript! Cargamos en nuestro <head> tanto jQuery como jquery.filedrop.js
    
    (function () {
        "use strict";
        jQuery(document).ready(function ($) {
            $('#uploader').filedrop({
                url: '',
                withCredentials: false,
                requestType : 'PUT',
                headers: {
                    'x-amz-acl': 'public-read',
                    'Access-Control-Allow-Origin': '*'
                },
                maxfiles: 25,
                maxfilesize: 20,
                beforeSend: function (file, i, done) {
                    $('#uploader ul').append('<li data-index="' + file.name + '">Subiendo <span>' + file.name + '</span></li>');
                    var that = this;
                    $.get("script.php", {filename: file.name }, function (data) {
                        that.url = decodeURIComponent(data);
                        done();
                    });
                },
                uploadFinished: function (i, file, response, time) {
                    // response is the data you got back from server in JSON format.
                    $('#uploader ul').find('li[data-index="' + file.name + '"]').css("color", "green");
                },
                globalProgressUpdated: function (progress) {
                    // progress for all the files uploaded on the current instance (percentage)
                    $('#uploader h3').html(progress + "%");
                    if (progress === 100)
                        $('#uploader h3').empty();
                },
                dragOver: function () {
                    $(this).addClass('over');
                },
                dragLeave: function () {
                    $(this).removeClass('over');
                },
                drop: function () {
                    $(this).removeClass('over');
                }
            });
        });
    })();
    

Y… listo! Ya tenemos nuestro drag&drop uploader teniendo como repositorio de los ficheros Amazon S3… Cargar vuestro index.html y arrastrar un fichero de una de vuestras carpetas de vuestro PC a esta región… voila! Id a vuestra cuenta de Amazon S3 y allí estará vuestro fichero!

Alguna duda? Dejad en los comentarios!!!

Espero que os sea de ayuda!

Un saludo!

EDIT: Para quien no le guste «copiar y pegar»… aquí tenéis el código del post

Salir de la versión móvil