Problema muy raro con la función copy

162 views
Skip to first unread message

socketBCN

unread,
Jul 16, 2010, 4:11:07 AM7/16/10
to Grupo de programadores PHP de Barcelona
Hola a todos!!

Tengo un problema bastante raro con copy y/o rename, son funciones muy
simples y faciles de utilizar, pero me estoy volviendo loco, me
explico:

La aplicación está bajo IIS 6.0 en windows 2003 y estoy usando php
5.2.8

El problema radica al subir un archivo al servidor, lo copio a una
carpeta temporal para validarlo, tras la validación, si es correcta,
muevo el archivo a la carpeta del usuario. La carpeta del usuario
puede tener hasta dos niveles diferentes dependiendo del tipo de
archivo. Parece fácil pero hay veces que me sucede una cosa extraña,
el archivo no se me mueve a la carpeta destino y php me dice que si
que se ha movido.

Os muestro el código. Bueno, parte de él porque el script es demasiado
grande, pero con esta parte es suficiente.

Código PHP:
if((!empty($_FILES["origen"])) && ($_FILES['origen']['error'] == 0))
{

$tipo = $_FILES["origen"]["type"];
$directorio_destino = 'X:/tmp/';

inserta_log('Archivo: '.basename($_FILES['origen']['name']),0);
inserta_log('Tipo: '.$tipo,0);

if (in_array($tipo,$tipos_soportados)){ //unicos tipo aceptados

$archivo = basename($_FILES['origen']['name']);
$extension = substr($archivo, strrpos($archivo, '.') + 1);

// creamos nombre unico
// ejemplo nombre: 1234567890.txt
$ahora = time();
while(file_exists($directorio_destino.$ahora.
$_SESSION["numero_sesion"])){
$ahora++;
}

//INDICAMOS EL PATH DONDE GUARDAR EL ARCHIVO
$archivo_tmp = $directorio_destino.$ahora.
$_SESSION["numero_sesion"];
if ((move_uploaded_file($_FILES['origen']['tmp_name'],
$archivo_tmp))) {
inserta_log('Fichero guardado en tmp OK',0);
} else {
inserta_log('Error al mover el fichero a tmp',1);
$error_global=true;
$msg_error = Literal(10);
}

} else {

inserta_log('Tipo de archivo incorrecto',1);
$error_global=true;
$msg_error = Literal(1007);
}

} else {
inserta_log('Error al subir el fichero',1);
$error_global=true;
$msg_error = Literal(10);
}

//validamos estructura fichero
if (!$error_global){
include('includes/validarFichero_class.php');
$validacion = new validar_fichero();
$resultado = $validacion ->valida($archivo_tmp,$_POST['tipo']);
if (!$resultado){
inserta_log('Estructura incorrecta',1);
$error_global=true;
$msg_error = Literal(5);
}
}


//movemos el cuaderno a su ubicacion correcta
if (!$error_global){

//comprobamos que las carpetas existan
$directorio_tipo_fichero = dirname($ruta_fichero);
$directorio_usuario = dirname($directorio_tipo_fichero);

inserta_log('Directorio fichero'.$directorio_tipo_fichero,0);
inserta_log('Directorio usuario'.$directorio_usuario,0);

if(!is_dir($directorio_usuario)){
inserta_log(' No existe directorio usuario',1);
mkdir($directorio_usuario);
if(!is_dir($directorio_usuario)){
inserta_log('Error al crear la carpeta usuario',1);
$msg_error=Literal(2);
$error_global=true;
}else{
inserta_log('Directorio creado correctamente',0);
}
}

if (!$error_global){
if(!is_dir($directorio_tipo_fichero)){
inserta_log(' No existe directorio tipo_fichero',1);
mkdir($directorio_tipo_fichero);
if(!is_dir($directorio_tipo_fichero)){
inserta_log('Error al crear la carpeta tipo_fichero',1);
$msg_error=Literal(2);
$error_global=true;
}else{
inserta_log('Directorio creado correctamente',0);
}
}
}

if (!$error_global){
inserta_log('Archivo tmp '.$archivo_tmp,0);
inserta_log('Nueva ruta fichero '.$ruta_fichero,0);
if (!copy($archivo_tmp, $ruta_fichero)) {
inserta_log('Error al mover el archivo');
$msg_error=Literal(2);
$error_global=true;
}else{
inserta_log('Archivo movido correctamente',0);
if (!file_exists($ruta_fichero)){
$error_global=true;
inserta_log('EL FICHERO NO EXISTE EN DESTINO!!!!!',1);
}else{
inserta_log('Archivo en destino comprobado correctamente',
0);
}
}
}
}
Como veis en el código voy imprimiendo un log, el log es el siguiente:
Código PHP:
20100709 07:57:18 086276t7ol4lkc9rgvr43ctm53 OK Archivo: prueba.txt
20100709 07:57:18 086276t7ol4lkc9rgvr43ctm53 OK Tipo: text/plain
20100709 07:57:18 086276t7ol4lkc9rgvr43ctm53 OK Fichero guardado en
tmp OK
20100709 07:57:18 086276t7ol4lkc9rgvr43ctm53 OK Directorio Fichero
X:/archivos/recibidos/usuario_1/tipo_1
20100709 07:57:18 086276t7ol4lkc9rgvr43ctm53 OK Directorio usuario
X:/archivos/recibidos/usuario_1
20100706 07:57:18 086276t7ol4lkc9rgvr43ctm53 KO No existe
directorio usuario
20100706 07:57:18 086276t7ol4lkc9rgvr43ctm53 OK Directorio creado
correctamente
20100706 07:57:18 086276t7ol4lkc9rgvr43ctm53 KO No existe
directorio fichero
20100706 07:57:18 086276t7ol4lkc9rgvr43ctm53 OK Directorio creado
correctamente
20100709 07:57:18 086276t7ol4lkc9rgvr43ctm53 OK Archivo tmp X:/tmp/
127865503854500000002146995
20100709 07:57:18 086276t7ol4lkc9rgvr43ctm53 OK Nueva ruta archivo
X:/archivos/recibidos/usuario_1/tipo_1/nuevo_nombre.txt
20100709 07:57:18 086276t7ol4lkc9rgvr43ctm53 OK Archivo movido
correctamente
20100709 07:57:18 086276t7ol4lkc9rgvr43ctm53 OK Archivo en destino
comprobado correctamente

Nunca he tenido ningun error ni en el log que genero yo ni el log de
php, pero de vez en cuando el archivo que he copiado a la carpeta
temporal no se me copia al directorio destino, lo raro es que php me
dice que lo ha movido correctamente y que la comprobación es correcta,
pero no es cierto ni se ha movido ni existe.

El tema ya no se por donde pillarlo, cada dia se suben alrededor de
100 archivos y tengo solo problemas con tres o cuatro de ellos, las
carpetas siempre se crean correctamente, los permisos son correctos,
ya que si no cantaria el log de php. He cambiado el copy por un rename
y la cosa es peor todavia, cuando sucede lo mismo el archivo
desaparece y no canta ningun error.

Los logs los tengo activados en E_ALL & ~E_NOTICE | E_STRICT y el
safe_mode a off. He intentado saber un poco mas alla con el backtrace
pero no consigo nada, supongo que es debido a que no se usarlo
decentemente.

Alguna sugerencia??

Muchas Gracias a todos.

Yago Ferrer

unread,
Jul 18, 2010, 8:48:54 PM7/18/10
to phpbar...@googlegroups.com, sock...@gmail.com
Hola socketBCN,

¿Por qué no pruebas usar try/catch en copy? Quizá devuelve más información sobre el error. 

try {
    copy($archivo_tmp, $ruta_fichero);
} catch (Exception $e) {
    $error_message = var_dump($e->getMessage());
    inserta_log("Ocurrió el siguiente error al copiar el fichero: " . $error_message);
}

Utiliza la clase Exception para capturar errores en llamada a funciones lugar de retorno true/false.

Exception tiene otros métodos útiles no solamente getMessage()

Saludos.

Yago Ferrer


2010/7/16 socketBCN <sock...@gmail.com>
Hola a todos!!

Tengo un problema bastante raro con copy y/o rename, son funciones muy
simples y faciles de utilizar, pero me estoy volviendo loco, me
explico:

La aplicación está bajo IIS 6.0 en windows 2003 y estoy usando php
5.2.8

El problema radica al subir un archivo al servidor, lo copio a una
carpeta temporal para validarlo, tras la validación, si es correcta,
muevo el archivo a la carpeta del usuario. La carpeta del usuario
puede tener hasta dos niveles diferentes dependiendo del tipo de
archivo. Parece fácil pero hay veces que me sucede una cosa extraña,
el archivo no se me mueve a la carpeta destino y php me dice que si
que se ha movido.

Os muestro el código. Bueno, parte de él porque el script es demasiado
grande, pero con esta parte es suficiente.
...

--
Yago Ferrer

socketBCN

unread,
Jul 20, 2010, 4:30:52 AM7/20/10
to Grupo de programadores PHP de Barcelona
Hola Yago,

He probado el try catch y no he conseguido nada. Por lo que he podido
leer sobre el try catch, las funciones php no sacan excepciones de
momento, si no que el try catch es para montarte tu mismo un control
de excepciones y depurar estas mismas con mas comodidad. De hecho si
provoco un error el try catch no hace nada.

No obstante, muchisimas gracias.

Seguire investigando haber si consigo algo.

Un saludo



Juanjo López Mellado

unread,
Jul 20, 2010, 5:01:51 AM7/20/10
to phpbar...@googlegroups.com
Hola.

Antes que nada, te sugiero separar todo este código en funciones más simples, te ayudará
a separar mejor la lógica y a seguir los errores.

En cualquier caso, yo investigaría el código que genera el fichero temporal. veo que lo haces
utilizando el timestamp actual y compruebas si ya existe. Mientras exista vas aumentando la
variable $ahora.

Todo este código lo tendrías que hacer en exclusión, porque nada te impide que otro proceso
corra el mismo código y te robe el nombre del fichero temporal.

Yo probaría a eliminar todo ese código y usar la función tmpfile()

No se si es ese el error, pero yo buscaría ahí primero.

Saludos.

Juanjo




--
Has recibido este mensaje porque estás suscrito al grupo "Grupo de programadores PHP de Barcelona" de Grupos de Google.
Para publicar una entrada en este grupo, envía un correo electrónico a phpbar...@googlegroups.com.
Para anular tu suscripción a este grupo, envía un correo electrónico a phpbarcelona...@googlegroups.com
Para tener acceso a más opciones, visita el grupo en http://groups.google.com/group/phpbarcelona?hl=es.




--
Juanjo López
http://www.linkedin.com/in/juanx

Sebastian Ayala

unread,
Jul 20, 2010, 5:03:23 AM7/20/10
to phpbar...@googlegroups.com
Hola, tal vez deberías ver de guardar el log cuando es correcto la subida de ficheros
 if ((move_uploaded_file($_FILES['origen']['tmp_name'], $archivo_tmp)))

Acá tendrías que ver que capada del sistema de falla y te da el error, si el sistema operativo, Apache o el PHP.

Con Window$ el tema de los permisos es muy simple a comparación de GNU-Linux, lo que tendrías que ver es tratar de tracear cuando esto ocurre exactamente, si acaso hace un copy del file y luego elimina el anterior me paso a veces que si luego de copiarlo al destino no lo puede borrar pasan cosas raras.

Proba dos path simples tipo d:\tmp1 y d:\tmp2 para mover entre ellos.

Bueno espero que te sea de utilidad.

Saludos


2010/7/20 socketBCN <sock...@gmail.com>
Reply all
Reply to author
Forward
0 new messages