Descripción y fuentes del upload PHP + AJAX con barra de progreso
Días atrás comenté que había estado trabajando en un pequeño experimento para conseguir implementar un sistema para realizar upload de archivos mediante PHP, que permitiera generar una barra de progreso, con la que controlar el estado de la carga de archivos en todo momento.
A continuación encontraréis disponible para descara el código fuente de dicho experimento y una pequeña descripción del paquete y de los requisitos para su puesta en marcha.
Contenidos del paquete
- /cgi-bin/upload.cgi: este es el CGI perl que se encarga de gestionar el upload, además de ir escribiendo todos los datos POST en un único archivo que nos permite controlar el total de datos cargados en el servidor en un momento determinado.
- /upload.php: es el documento principal, que contiene el código HTML y JS necesario para crear dinámicamente los campos file y el listado de archivos que vamos a cargar al servidor, así como dibujar dinámicamente la barra de progreso a partir de las respuestas recibidas por AJAX.
- /ajax_process.php: es el script PHP que recibirá las peticiones AJAX, comprobará el estado del upload y devolverá una respuesta XML con datos como el tamaño total del archivo, la cantidad de datos cargada, los nombres de los archivos...
- /xml.class.php: un par de clases para crear/parsear datos XML.
- /img: contiene dos imágenes opcionales: un fondo animado para la barra de progreso y un icono "en proceso".
Ejemplo en vivo
Podéis ver un ejemplo real en la URL http://www.obolog.com/upload.php
Descarga del código fuente
Podéis descargar un ZIP con el código fuente desde http://www.obolog.com/downloads/ajax_upload.zip
Créditos
La idea de la carga múltiple de archivos la tomé de : Upload multiple files with a single file element
El código del script CGI que permite el upload y la escritura de los datos raw POST es una modificación de Mega Upload, de raditha.com.
Toda la implementación de AJAX se ha llevado a cabo usando la librería Jquery , consiguiendo una simplificación extrema ( vereis que todo el código necesario para la creación dinámica de campos file y la escritura y modificación de la barra de progreso supera en poco las 50 líneas ).
Y bueno, eso es todo amigos. Que lo disfrutéis. Preguntas y dudas a los comentarios.
- Deja tu comentario (128)




Comentarios
BUeno, bueno... Felicidades! (auqn no me he enterado de res!) Pero Albert, ya sabes que tienes una cita conmigo... un punto más que se agrega a mi lista de NS/NC...
:-)
No Habla Espanol, but I really want to get this working on my site....when I test it out It just sits there....loading.
EH EH!! què vol dir això? aqui hi ha tema i jo no m'he enterat? això no pot ser...
Ponte a la cola, dude.
Albert,
Me parece excelente el script. El mejor de todos los que vi. El problema es que no logro que funcione. Cuando cargo archivos la barra no se completa y el archivo nunca llega. Disculpa la molestia, hay algo que me este olvidando? o el servidor requiere de alguna libreria en particular?
Desde ya muchas gracias !
Agh! Llevas toda la razón, Alejandro! El código es la adaptación del ejemplo que colgué, y precisamente en ese ejemplo, para no saturar el servidor, simplemente no hacía nada con los archivos subidos, se quedaban en la carpeta temporal...
Así pues, para conseguir que el script termine de ser funcional, y poder trabajar con los archivos, faltaría mover los temporales a una carpeta de trabajo. Eso se podría hacer tanto directamente desde el CGI, o mediante un script PHP al que redireccionara éste. Espero poder subir el script modificado en un par de días. Os informaré con un comentario en cuanto lo haya actualizado.
Siento el descuido!
Muy bueno! felicidades, me gustaría contactar contigo para hablar sobre un proyecto de web, estoy buscando un programador joven, innovador, amante de internet y arriesgado.
Si te sientes identificado, será un placer conocerte,
ups, he escrit en castella, soc de Manresa ;-)
¿Cuando queda pronta la modificación del script? Veo que los post llegan hasta el 11/04/06 y aún no hay nada..... es que la ansiedad dejo de ser un valor?
Disculpad la tardanza... Hace algo más de una semana me trasladé al nuevo piso, y aún no tengo internet allí. Si los operadores de Jazztel no me han mentido... en unas dos semanas habrán llevado a cabo la portabilidad y la activación de la línea, así que para entonces, podré colgar los cambios.
Mientras tanto... sólo puedo conectar desde el trabajo.
Ola! Adorei seu script, mas estou um problema. Tudo funciona perfeitamente, mas para onde vao meus arquivos no servidor ?
Muito obrigado, se puder responder no meu email, ou no meu msn: fabricio_massula@hotmail.com
Obrigado
Buenismo, mira gracias !
Lo baje de nuevo y anda perfecto. Que tendria que modificar para recuperar los archivos que subo? o sea, moverlos a una carpeta
Epale!!! está súper tu explicación!
(Y)
Que tal men, hace unos dias curiosiando por la red me encontre tu script y mi reaccion fue como si hubiera encontrado el santo grial jejejeje
en pocas alabras: esta muy bueno el script,
pero no seas malo sube el script funcional
Hola que tal,
Estoy impresionado por las posibilidades de AJAX, pero he tratado de instalar el script en mi servidor y no consigo que haga nada. Se queda "cargando..." y no hace nada.
Es muy posible que haya cometido algún fallo al instalarlo, por lo que cualquier ayuda será bienvenida. La estructura del servidor es similar a la de todos
/var/www/vhosts/dominio.com/cgi-bin
/var/www/vhosts/dominio.com/httpdocs
/var/www/vhosts/dominio.com/tmp
...
En el archivo ajax_process.php que debería poner aquí:
<?
// Put here the same folder that in CGI
define ( "TEMP_DIR", $_SERVER['DOCUMENT_ROOT']."/tmp/" );
//---------------->
y en upload.cgi
# variable values. This folder will host the raw post data during the upload.
$tmp_dir="/var/www/vhosts/obolog.com/httpdocs/tmp";
SaludosSaludos
Soy yo otra vez,
Ya he conseguido que funcione. Está muy bien.
Entiendo por "length" tal vez la barra de progreso, eso puede ser porque estas ejecutando "upload.php" desde un directiorio sin ser el raíz.. entonces necesitas en el "<form" de este archivo colocar en la parte de action: action="/cgi-bin .... una barra inclinada para decirle que esta desde el raíz. Me atraso un poco en mandar la solución porque debo entregar un trabajo para el lunes 12. La solución si alguien quiere maltratarse un poco está bajando el megaupload y ver el archivo llamado upload2.php, entonces suben ese archivo también y en upload.php después de $("#ok_status").show(); colocan abajo:
self.location.href ='upload2.php?sid=<?=$sid?>';
esto redirije al upload2.php luego de subido el archivo pero antes deben sacar de ajax_upload.php las 4 líneas que hay como estas:
unlink(TEMP_DIR.$_REQUEST["sid"]."_signal");
ya que upload2.php toma esos archivos que se borran con unlink y estos archivos son muy importantes porque contienen la info de los archivos subidos para dividirlos del temp original creado al subir, luego si se quiere al final del upload2.php se pueden borrar con las líneas esas de unlink que eliminaron de archivo ajax. Recuerden que en upload2.php hay una línea que mueve los archivos...algo así:
rename($file['tmp_name'][$i], aquí_el_directorio_y_el_nuevo_nombre_del_archivo);
Pueden crear algo con ese bucle o el nombre original deberían sacarlo con un "explode" ya que sino da error c:\\directorio\\1.jpg por algo así, entonces con explode:
$archtemp=explode('\\',$file['tmp_name'][$i]);
y agregan:
$cuento=count($archtemp);
if ($cuento>0)
{ $archivo=$archtemp($cuento-1); }
else
$archivo=$archtemp;
$archivo=str_replace(' ','_',$archivo);
medio rebuscando... aun no lo probe. Espero que alguien de esta forma pueda hacerlo andar, de lo contrario hay que esperar hasta que me vea libre... de mis responsabilidades... ¡suerte!
¡Me aburrí!, me tome un tiempito y lo modifiqué, en cada archivo puse un comentario así es más fácil que ande. El enlace demora unos segundos para permitir la descarga, luego aparece:Click here to download file.
http://www.mysharefile.com/v/f4rwrn0b/upload_ajax.zip.html
Los créditos son para Albert García, claro está, lo mío es solo un retoquesito.
Cuidado, acá mando otra vez el archivo zip, ya que el anterior dentro de upload2.php no tenía los unlink para eliminar los archivos temporales una vez subidos, ahora los borra. Aquí el archivo modificado:
http://www.mysharefile.com/v/1230849/upload_ajax_2.zip.html
Eso es todo, espero que ande bien, luego sería una buena idea renombrar el archivo upload.cgi por un nombre raro tipo up_ajax_pro.cgi y en upload.php luego cambiar el <form... con el nuevo nombre por un tema de seguridad... me puse paranoico.
En efecto, como habían comentado por ahí arriba, el script estaba incompleto, puesto que sólo controlaba la carga del archivo, no trataba los archivos subidos, ni los copiaba a ninguna parte. Esto fué debido a que usé como modelo el propio experimento que usaba en esta misma web, donde simplemente realizo el control de upload, para luego eliminar los archivos de control ( _qstring, _flenght, _signal... ), y dejar los archivos subidos en el temporal, donde son eliminados periódicamente.
Para conseguir la completa funcionalidad del script basta con añadir un print "location:%url_del_script%" al final del CGI, especificando el URL del script que tratará el upload, como si de un upload simple de PHP se tratara. He modificado el script subido para incorporar este cambio.
Recordad, como también os han apuntado por ahí arriba, que es importante que tengáis en cuenta las rutas a los archivos ( relativas, absolutas... )cuando configuréis los scripts.
Aclaración: los archivos *_qstring, *_flenght, *_signal... SÍ deben borrarse al finalizar el upload, puesto que sólo sirven para que el control AJAX pueda ir midiendo el progreso de la carga. No son realmente los archivos subidos, si no los datos en bruto del envío POST.
Un saludo y disculpad la demora. ;)
Hi g0nzo!
Are you sure that your Apache's config allow cgi-script execution in the folder that contains upload.cgi?
Take a look at http://httpd.apache.org/docs/2.0/howto/cgi.html
I hope this help you.
Regards!
Hola a todos Necesito un favor
Necesito hacer que varios usuarios puedan subir y bajar archivos por ejemplo de imagenes desde una web, es decir que un usuario "x" suba un archivo 1.jpg y que otro usuario "Z" le guste ese archivo y lo baje, es decir una carpeta en donde se puedan alojar archivos de imagenes, que esten al acceso de los usuarios, que puedan subir y bajarlos cuando quieran, buscarlos, etc...
Por favor si alguien me puede dar una mano en esto.... si me pueden pasar los script, un ejemplo, se los agradecería mucho...
saludos Karina
Hola Karina, me encuentro en tu misma situación y tengo varias dudas:
1- Para que funcione AJAX es necesario instalar algún interprete en el servidor? Tengo entendido que se basa en JavaScript, por lo que no lo tengo muy claro.
2- El megaupload funciona sin AJAX?
3- Si AJAX es obligatorio, conocen algún otro fichero PHP, Perl, JS o HTM para subir archivos a un servidor? No es imprescindible que muestre la barra de progreso.
4- Supone algún riesgo para el servidor el uso de su script? Me gustaria limitar por ejemplo el tamaño y las extensiones para los ficheros que se suban al servidor. Las extensiones se pueden configurar fácilmente en la página upload.php pero no se si esto es suficiente o si hay que modificar algún documento más.
Nada más por mi parte, muchísimas gracias por compartir su trabajo y por su ayuda. Un cordial saludo.
Alfredo,
No consigo que funcione tu ejemplo.
Los 4 archivos temporales que se copin en tmp_upload se generan correctamente, pero despues no soy capaz de copiar el archivo al directorio definitivo.
Me podrías ayudar?
Gracias
Hola, estuve viendo el script y funciona muy bien sólo que algunas veces el script genera un error de permisos entre el CGI y el PHP ya que el php muchas veces no puede acceder directamente a la carpeta de temporales si no ha sido el mismo script quien lo hacreado. Estuve intentando mover los archivos desde perl pero mis conocimentos en perl son pocos.
Quisiera preguntar si alguien sabe como se interpreta el siguiente comando que existe en el javasscript
$("#Submit").set("disabled","disabled"); (realmente no se que es el $('#elemento'). blabla).
Desde ya muchas gracias y el script funciona de maravillas.
Saludos
Dde y muchas gracias Saludos a todos
Miguel, no sé cual es tu problema al copiar los archivos al nuevo dir, o que error te genera el código.
Joel, tal vez sería bueno que pruebes el script desde un hosting linux real.
Enrique, eso es para habilitar o deshabilitar el botón de subida cuando por lo menos tenés un archivo ya seleccionado.
Karina, eso que pedís al igual que alguien que dijo por allí de subir fotos y al mismo tiempo crear una miniatura es bastante complejo y al mismo tiempo muy personalizado a cada proyecto, se hace imposible desde aquí informar algo así.
Enrique, esto es para ti:
$("#Submit").set("disabled","disabled");
eso es una sentencia creada a partir de la librería jquery que en su nueva versión beta sería <<jQuery("#Submit").set("disabled","disabled"); >> pero seguirá siendo funcional la forma que nos presentas.
Paso a explicartelo
$() es una funcion que nos devuelve un array de objetos que cumplan una serie de requisitos, los requisitos son los que se encuentran dentro de los (), por ejemplo #Submit que indica todos los objetos que tengan como id "Submit", si se hubiese puesto ".Submit" habrían sido todos los elementos con la clase css "Submit", o si se quisiese indicar todos los input del tipo submit: 'input[@type="submit"]'
el .set es otra función, sí como lees, es que jQuery implementa la concatenación de funciones y se pueden usar funciones sobre los objetos devueltos por las anteriores funciones.
.set lo que hace es establecer un parámetro o atributo de objeto a lo que se le diga, es decir, .set("disabled","disabled") establece el parametro disabled a disabled, sería como tener esto:
<input type="submit" id="Submit" value="Enviar">
y tras interpretarse el javascript quedase algo como
<input type="submit" id="Submit" value="Enviar" disabled="disabled">
Para aprender mas de jQuery te aconsejo que te documentes tanto en la pagina oficial como en tantas otras que hay sobre la librería.
Un saludo
Alfredo gracias por responder.
El problema es que en tu ejemplo aparece una carpeta "uploads" donde se supone que el script upload2.php debería copiar el archivo, borrando a su vez los temporales creados. A mi me borra los temporales perfectamente, pero en la carpeta uploads no se copia nada (por supuesto tengo permiso 777 para esa carpeta).
Un saludo
Muy bueno tu codigo man, pero tengo un pequeño problemita ... y es que yo lo que necesito es poder subir un zip, modifico la funcion javascript que verifica la extension y deja de funcionar .... te pego el codigo:
if ( false != elem )
{
filepath = elem.value.split("\\");
filename = filepath[filepath.length-1];
extensionpath = filename.split(".");
extension = extensionpath[extensionpath.length-1];
/*if( !extension.match(/(jpg)|(jpeg)/) )
{
alert ( "Sólo se permite subir imágenes: jpg." );
return false;
}*/
$(elem).hide();
$("#file_list").append("<li style='display:none'>• "+filename+" <a xhref='javascript:;' onclick='delFile(this,"+($("#file_list li").size()+1)+")' style='color:red'>[x]</small></a></li>\n");
$("#file_list li:last").slideDown("slow");
}
Espero que alguien me pueda ayudar, muchas gracias ^^
Hola, me parece super bueno este script. Lo que pasa es que yo voy un poco pez en esto
y me gustaria saber dos cosillas.
1. se puede ejecutar este script en cualquier ordendor? no es necesario tener linux, verdad?
2. Hay que configurar algún parámetro o algo? es que no me funciona, aparece la barra de estado de la descarga, pero ya esta, no se completa ni nada.
Os agradezco un montón la ayuda.
Hola a todos, ante todo enhorabuena por la aplicacion es muy interesante. yo he estado dandole vueltas , y mi problema es que no se donde se alojan los archivos... dado que solo se fragmentan en el temporal y despues, se borran con el unlink...pero, no consigo saber donde se suben , es mas no consigo saber que lineas tocar para poder cambiar el directorio donde se suban los archivos.
Para aquellos que solo vean la barra de descarga pero esta no se inicie, probad a desabilitar cualquier antivirus o firewall que tengais, basicamente por que AJAX utiliza puertos que podeis tener cerrado.
Un saludo
Hola gente, me parece muy bueno el script pero no logro probarlo en mi hosting. La barra de progreso no avanza... El cgi tiene permisos 755 el temp dir creo haberlo puesto bien /home/.../public_html/tmp_upload pero no doy con mi error... Si alguien me puede orientar se lo agradeceria ya que necesitaría algo asi. Luego si puedo correrlo en mi hosting necesitaré que me aclaren otras dudas.
Gracias