listar - php ftp example
Cómo determinar si un archivo todavía se está transfiriendo a través de ftp (5)
Tengo un directorio con archivos que necesitan procesarse en un lote con PHP. Los archivos se copian en el servidor a través de FTP. Algunos de los archivos son muy grandes y tardan mucho tiempo en copiarse. ¿Cómo puedo determinar en PHP si aún se está transfiriendo un archivo (para poder omitir el procesamiento en ese archivo y procesarlo en la siguiente ejecución del proceso por lotes)?
Una posibilidad es obtener el tamaño del archivo, esperar unos minutos y verificar si el tamaño del archivo es diferente. Esto no es impermeable porque hay una pequeña posibilidad de que la transferencia se haya detenido por unos momentos ...
No es un truco realmente agradable, pero es simple :-), lo mismo que puedes hacer con filemtime
$result = false;
$tryies = 5;
if (file_exists($filepath)) {
for ($i=0; $i < $tryies; $i++) {
sleep(1);
$filesize[] = filesize($filepath);
}
$filesize = array_unique($filesize);
if (count($filesize) == 1) {
$result = true;
} else {
$result = false;
}
}
return $result;
Algunos servidores FTP permiten ejecutar comandos cuando ocurre cierto evento. Entonces, si su servidor FTP lo permite, puede crear un esquema de señalización simple para que su aplicación sepa que el archivo se ha cargado con más o menos éxito (más o menos es porque no sabe si el usuario tenía la intención de cargar el archivo) completamente o en partes). El esquema de señalización puede ser tan simple como la creación del archivo "uploaded_file_name.ext.complete", y usted controlará la existencia de archivos con la extensión ".complete".
Ahora puede verificar si puede abrir el archivo para escribir. La mayoría de los servidores FTP no te permitirán hacer esto si el archivo se está cargando.
Otro enfoque mencionado por Mat es el uso de técnicas específicas del sistema para verificar si el archivo está abierto por otro proceso.
Nuestro administrador de servidor sugirió ftpwho, que muestra qué archivos se transfieren actualmente.
http://www.castaglia.org/proftpd/doc/ftpwho.html
Entonces, la solución es analizar la salida de ftpwho para ver si se está transfiriendo un archivo en el directorio.
Una de las formas más seguras de hacerlo es subir los archivos con un nombre temporal y cambiarles el nombre una vez que la transferencia haya finalizado. Su programa debe omitir archivos con el nombre temporal (una simple extensión funciona bien). Obviamente, esto requiere que el cliente (cargador) coopere, por lo que no es ideal.
[Esto también le permite eliminar transferencias fallidas (parciales) después de un período de tiempo dado si lo necesita.]
Todo lo que se base en sondear el tamaño del archivo es agresivo e inseguro.
Otro esquema (que también requiere cooperación del cargador) puede implicar primero cargar el hash y el tamaño del archivo, luego el archivo real. Eso le permite saber cuándo se realiza la transferencia y si es coherente. (Hay muchas variantes en torno a esta idea).
Algo que no requiere cooperación del cliente es verificar si el archivo está abierto por otro proceso o no. (¿Cómo lo hace depende del sistema operativo? No sé de una versión interna de PHP que hace esto. lsof
y / o fuser
se pueden utilizar en una variedad de plataformas de tipo Unix, Windows tiene API para esto). Si otro proceso tiene el archivo abierto, es probable que aún no esté completo.
Tenga en cuenta que este último enfoque puede no ser infalible si permite reiniciar / reanudar las cargas, o si su software de servidor FTP no mantiene el archivo abierto durante toda la transferencia, entonces YMMV.
La mejor forma de comprobarlo sería intentar obtener un bloqueo exclusivo en el archivo utilizando el rebaño. El proceso sftp / ftp utilizará las bibliotecas fopen.
// try and get exclusive lock on file
$fp = fopen($pathname, "r+");
if (flock($fp, LOCK_EX)) { // acquire an exclusive lock
flock($fp, LOCK_UN); // release the lock
fclose($fp);
}
else {
error_log("Failed to get exclusive lock on $pathname. File may be still uploading.");
}