Inicio  |  Noticias  |  Foro  |  Blogs  |  Galerías  |  Eventos  |  Reportajes 
    Ca l'Avi Blogs
Hola Visitante   Registrate   Logueate 

Como subir múltiples ficheros
oscar - 23-10-2009

Vamos a empezar este blog destripando un poco la pàgina de Ca l´Avi.net.

Uno de los retos en los que me encontré, fué el como subir múltiples ficheros, es decir, cuando creo una galería de imágenes, como hacer para subir 20 o 30 imágenes a vez en vez de ir de una en una.

Una de las soluciones elegidas fue usar Fancy Upload, una aplicación personalizable para subir múltiples archivos hecha en AJAX, que por lo tanto, puede ser integrada en diferenes lenguajes como PHP, ASP, etc .... Quizá la parte más complicada fué la integración, ya que en el caso de Calavi, además de subir las imágenes de forma ágil, había que guardar un registro en la base de datos para poder vincular esa imágen a los comentarios que pudieran generarse. Por otro lado empecé a usar la versión 2.0, cosa que me dió muchos dolores de cabeza porque con según que navegadores y que versiones de flash player no funcionaba, pero con la versión 3.0 se arreglaron los problemas, o casi.

Los archivos necesarios para utilizar Fancy Upload son: MooTools 1.11Swiff.Uploader.js, Swiff.Uploader.swf, FancyUpload2.js, Uploader.js, Fx.ProgressBar.js, images

Mi integración a sido la siguiente:

En el archivo subir.php se declaran los estilos de la aplicación, se cargan los .js y ponemos unas funciones de javascript

<style type="text/css">
.swiff-uploader-box a {
    display: none !important;
}
 
/* .hover simulates the flash interactions */
#demo-status {
    padding: 10px 15px;
    width: 420px;
}
 
#demo-status .progress {
    background: url(imatges/progress-bar/progress.gif) no-repeat;
    background-position: +50% 0;
    margin-right: 0.5em;
    vertical-align: middle;
}
 
#demo-status .progress-text {
    font-size: 0.9em;
    font-weight: bold;
}
 
#demo-list {
    list-style: none;
    width: 450px;
    margin: 0;
}
 
#demo-list li.validation-error {
    padding-left: 44px;
    display: block;
    clear: left;
    line-height: 40px;
    color: #8a1f11;
    cursor: pointer;
    border-bottom: 1px solid #fbc2c4;
    background: #fbe3e4 url(imatges/failed.png) no-repeat 4px 4px;
}
 
#demo-list li.file {
    border-bottom: 1px solid #eee;
    background: url(imatges/file.png) no-repeat 4px 4px;
    overflow: auto;
}
#demo-list li.file.file-uploading {
    background-image: url(imatges/uploading.png);
    background-color: #D9DDE9;
}
#demo-list li.file.file-success {
    background-image: url(imatges/success.png);
}
#demo-list li.file.file-failed {
    background-image: url(imatges/failed.png);
}
 
#demo-list li.file .file-name {
    font-size: 1.2em;
    margin-left: 44px;
    display: block;
    clear: left;
    line-height: 40px;
    height: 40px;
    font-weight: bold;
}
#demo-list li.file .file-size {
    font-size: 0.9em;
    line-height: 18px;
    float: right;
    margin-top: 2px;
    margin-right: 6px;
}
#demo-list li.file .file-info {
    display: block;
    margin-left: 44px;
    font-size: 0.9em;
    line-height: 20px;
    clear
}
#demo-list li.file .file-remove {
    clear: right;
    float: right;
    line-height: 18px;
    margin-right: 6px;
}
</style>

<script type="text/javascript" src="mootools.js"></script>
<script type="text/javascript" src="Swiff.Uploader.js"></script>
<script type="text/javascript" src="Fx.ProgressBar.js"></script>
<script type="text/javascript" src="FancyUpload2.js"></script>
<script type="text/javascript">
window.addEvent(´domready´, function() { // wait for the content
 
    // our uploader instance
 
    var up = new FancyUpload2($(´demo-status´), $(´demo-list´), { // options object
        // we console.log infos, remove that in production!!
        verbose: true,
 
        // url is read from the form, so you just have to change one place
        url: $(´form-demo´).action,
 
        // path to the SWF file
        path: ´Swiff.Uploader.swf´,
 
        // remove that line to select all files, or edit it, add more items
        typeFilter: {
            ´Images (*.jpg, *.jpeg, *.gif, *.png)´: ´*.jpg; *.jpeg; *.gif; *.png´
        },
 
        // this is our browse button, *target* is overlayed with the Flash movie
        target: ´demo-browse´,
 
        // graceful degradation, onLoad is only called if all went well with Flash
        onLoad: function() {
            //$(´demo-status´).removeClass(´hide´); // we show the actual UI
            //$(´demo-fallback´).destroy(); // ... and hide the plain form
 
            // We relay the interactions with the overlayed flash to the link
            this.target.addEvents({
                click: function() {
                    return false;
                },
                mouseenter: function() {
                    this.addClass(´hover´);
                },
                mouseleave: function() {
                    this.removeClass(´hover´);
                    this.blur();
                },
                mousedown: function() {
                    this.focus();
                }
            });
 
            // Interactions for the 2 other buttons
 
            $(´demo-clear´).addEvent(´click´, function() {
                up.remove(); // remove all files
                return false;
            });
 
            $(´demo-upload´).addEvent(´click´, function() {
                up.start(); // start upload
                return false;
            });
        },
 
        // Edit the following lines, it is your custom event handling
 
        /**
         * Is called when files were not added, "files" is an array of invalid File classes.
         *
         * This example creates a list of error elements directly in the file list, which
         * hide on click.
         */
        onSelectFail: function(files) {
            files.each(function(file) {
                new Element(´li´, {
                    ´class´: ´validation-error´,
                    html: file.validationErrorMessage || file.validationError,
                    title: MooTools.lang.get(´FancyUpload´, ´removeTitle´),
                    events: {
                        click: function() {
                            this.destroy();
                        }
                    }
                }).inject(this.list, ´top´);
            }, this);
        },
 
        /**
         * This one was directly in FancyUpload2 before, the event makes it
         * easier for you, to add your own response handling (you probably want
         * to send something else than JSON or different items).
         */
        onFileSuccess: function(file, response) {
            var json = new Hash(JSON.decode(response, true) || {});
 
            if (json.get(´status´) == ´1´) {
                file.element.addClass(´file-success´);
                file.info.set(´html´, ´<strong>Imagen subida:</strong> ´ + json.get(´width´) + ´ x ´ + json.get(´height´) + ´px, <em>´ + json.get(´mime´) + ´</em>)´);
            } else {
                file.element.addClass(´file-failed´);
                file.info.set(´html´, ´<strong>Error al subir la imagen:</strong> ´ + (json.get(´error´) ? (json.get(´error´) + ´ #´ + json.get(´code´)) : response));
            }
        },
 
        /**
         * onFail is called when the Flash movie got bashed by some browser plugin
         * like Adblock or Flashblock.
         */
        onFail: function(error) {
            switch (error) {
                case ´hidden´: // works after enabling the movie and clicking refresh
                    alert(´To enable the embedded uploader, unblock it in your browser and refresh (see Adblock).´);
                    break;
                case ´blocked´: // This no *full* fail, it works after the user clicks the button
                    alert(´To enable the embedded uploader, enable the blocked Flash movie (see Flashblock).´);
                    break;
                case ´empty´: // Oh oh, wrong path
                    alert(´A required file was not found, please be patient and we fix this.´);
                    break;
                case ´flash´: // no flash 9+ :(
                    alert(´To enable the embedded uploader, install the latest Adobe Flash plugin.´)
            }
        }
 
    });
 
});
</script>

Fijémonos cuando declaramos la variable up, en ella hemos de indicar que archivos queremos subir (indicando la extensión), y la ruta de la aplicación flash (Swiff.Uploader.swf), declarado todo esto, dentro del código HTML hemos de montar el menú de las 3 opciones (Seleccionar, Limpiar y Subir)

La parte de código correspondiente sería:

<form action="up.php?galeria=<?php echo $gal; ?>&id=<?php echo $id; ?>&clog=<?php echo $uploader; ?>" method="post" enctype="multipart/form-data" id="form-demo">
            <div id="demo-status" class="hide" align="center">
                <p>
                    <a href="#" id="demo-browse">Seleccionar Imágenes</a> |
                    <a href="#" id="demo-clear">Limpiar</a> |
                    <a href="#" id="demo-upload">Subir</a>
                </p>
                <div>
                    <strong class="overall-title">Overall progress</strong><br />
                    <img src="imatges/barra_upload.gif" class="progress overall-progress" />
                </div>
                <div>
                    <strong class="current-title">File Progress</strong><br />
                    <img src="imatges/barra_upload.gif" class="progress current-progress" />
                </div>
                <div class="current-text"></div>
            </div>
         
            <ul id="demo-list"></ul>
            </form>

Os fijareis que hago una llamada a up.php con parámetros, este archivo se encarga de gestionar cada fichero que se le pasa por el formulario, es decir, cada imágen, y se ha de tratar como si hicierais un simple upload en el lenguage que sea, como PHP o el que sea

<?php
include("conex_bbdd.php");
$galeria = $_GET["gal"];
$id = $_GET["id"];
$clog = $_GET["user"];

$result = array();

$result[´time´] = date(´r´);
$result[´addr´] = substr_replace(gethostbyaddr($_SERVER[´REMOTE_ADDR´]), ´******´, 0, 6);
$result[´agent´] = $_SERVER[´HTTP_USER_AGENT´];

if (count($_GET)) {
    $result[´get´] = $_GET;
}
if (count($_POST)) {
    $result[´post´] = $_POST;
}
if (count($_FILES)) {
    $result[´files´] = $_FILES;
}

$error = false;

//aplicamos filtros
if (!isset($_FILES[´Filedata´]) || !is_uploaded_file($_FILES[´Filedata´][´tmp_name´])) {
    $error = ´Invalid Upload´;
}

if (!$error && $_FILES[´Filedata´][´size´] > 5 * 1024 * 1024)
{
    $error = ´Please upload only files smaller than 5Mb!´;
}

if (!$error && !($size = @getimagesize($_FILES[´Filedata´][´tmp_name´]) ) )
{
    $error = ´Please upload only images, no other files are supported.´;
}

if (!$error && !in_array($size[2], array(1, 2, 3, 7, 8) ) )
{
    $error = ´Please upload only images of type JPEG, GIF or PNG.´;
}

if (!$error && ($size[0] < 25) || ($size[1] < 25))
{
    $error = ´Please upload an image bigger than 25px.´;
}

//si ha entrado en alguno de los filtros devolvemos el error
if ($error) {

    $return = array(
        ´status´ => ´0´,
        ´error´ => $error
    );

} else { //todo ok
    $return = array(
        ´status´ => ´1´,
        ´name´ => $_FILES[´Filedata´][´name´]
    );

    // Our processing, we get a hash value from the file
    $return[´hash´] = md5_file($_FILES[´Filedata´][´tmp_name´]);

    // ... and if available, we get image data
    $info = @getimagesize($_FILES[´Filedata´][´tmp_name´]);

    if ($info) {
        $return[´width´] = $info[0];
        $return[´height´] = $info[1];
        $return[´mime´] = $info[´mime´];
    }

    if (copy($_FILES[´Filedata´][´tmp_name´], "../imagenes/" . $galeria . "/" . $_FILES[´Filedata´][´name´])) {
        //insertamos
        mysql_query("INSERT INTO calavi_imagenes (user, id_foto, img) VALUES ($clog . "´, $id, ´galeria/" . $galeria . "/" . $_FILES[´Filedata´][´name´] . "´)", $db);
        $status = "Archivo subido: <b>".$_FILES[´Filedata´][´name´]."</b>";
    } else {
        $status = "Error al gestionar el archivo";
    }

    if (isset($_REQUEST[´response´]) && $_REQUEST[´response´] == ´xml´) {
        // header(´Content-type: text/xml´);
   
        // Really dirty, use DOM and CDATA section!
        echo ´<response>´;
        foreach ($return as $key => $value) {
            echo "<$key><![CDATA[$value]]></$key>";
        }
        echo ´</response>´;
    } else {
        // header(´Content-type: application/json´);
   
        echo json_encode($return);
    }
}?>

Ahora vienen los problemas con los que me he encontrado y con los que estoy en vias de solucionar. Cuando un archivo es demasiado grande suele dar error de Timeout o alguno similar son su señal de alerta y pueden pasar 2 cosas, que se suba o que no se suba el archivo, y después toda la cola de archivos queda "colgada", volviendo a tener que seleccionar todos los archivos pendientes, aunque he tocado el archivo Swiff.Uploader.js, en el cual podemos marcarle límites de tamaño y tiempo, creo que el problema es más de hosting que de la aplicación.

 Comentarios


02-10-2014 Notificar Abuso
04-10-2014 Notificar Abuso
12-10-2014 Notificar Abuso
13-10-2014 Notificar Abuso
16-05-2016 Notificar Abuso
16-05-2016 Notificar Abuso
08-08-2016 Notificar Abuso
14-08-2016 Notificar Abuso
24-09-2016 Notificar Abuso

Para poder comentar has de estar logado en Ca l'Avi


Artículos anteriores

Redondear decimales, hacia arriba y hacia abajo en PHP
Como crear URLs amigables con PHP
Como disminuir el peso de las imágenes con PHP (Parte 2)
Como disminuir el peso de las imágenes con PHP
Como subir múltiples ficheros

 Ver todos 



Resolución mínima de 1024x768© - Portal desarrollado por Softilus para Calavi.net - Copyright 2009, todos los derechos reservados