Cuando utiliza la función PHP copy, la operación copia ciegamente sobre el archivo de destino, incluso si ya existe. ¿Cómo se puede copiar un archivo de forma segura, solo se realiza la copia si no hay un archivo existente?¿Cómo se copia un archivo en PHP sin sobreescribir un archivo existente?
Respuesta
La solución obvia sería llamar al file_exists para verificar si el archivo existe, pero hacerlo podría causar una condición de carrera. Siempre existe la posibilidad de que el otro archivo se creará entre cuando llame al file_exists y cuando llame al copy. La única manera segura de verificar si el archivo existe es usar fopen.
Cuando llame al fopen, establezca el modo en 'x'. Esto indica fopen para crear el archivo, pero solo si no existe. Si existe, fopen fallará, y sabrá que no pudo crear el archivo. Si tiene éxito, tendrá creado un archivo en el destino que puede copiar de forma segura. Código de la muestra es el siguiente:
// The PHP copy function blindly copies over existing files. We don't wish
// this to happen, so we have to perform the copy a bit differently. The
// only safe way to ensure we don't overwrite an existing file is to call
// fopen in create-only mode (mode 'x'). If it succeeds, the file did not
// exist before, and we've successfully created it, meaning we own the
// file. After that, we can safely copy over our own file.
$filename = 'sourcefile.txt'
$copyname = 'sourcefile_copy.txt'
if ($file = @fopen($copyname, 'x')) {
// We've successfully created a file, so it's ours. We'll close
// our handle.
if ([email protected]($file)) {
// There was some problem with our file handle.
return false;
}
// Now we copy over the file we created.
if ([email protected]($filename, $copyname)) {
// The copy failed, even though we own the file, so we'll clean
// up by itrying to remove the file and report failure.
unlink($copyname);
return false;
}
return true;
}
Creo que respondió su propia pregunta: verifique que el archivo de destino exista antes de realizar la copia. Si el archivo existe, omita la copia.
Actualización: veo que realmente respondiste tu propia pregunta. Usted menciona las condiciones de carrera, pero si usted encuentra que el archivo ya existe, ¿cómo se sabe que:
- el archivo que ya está allí es realmente la persona que desea copiar
- el otro proceso de copiar el archivo ha completado su trabajo (los datos del archivo es todo lo que hay)
- la otra copia el archivo de proceso no va a fallar (y dejar un archivo incompleto, o borrar el archivo nuevo)
Creo que se debería considerar estas preguntas al diseñar una solución a su problema.
Intente utilizar la función link()
en lugar de copy()
.
function safe_copy($src, $dest) {
if (link($src, $dest)) {
// Link succeeded, remove old name
unlink($filename);
return true;
} else {
// Link failed; filesystem has not been altered
return false;
}
}
Desafortunadamente, esto será no trabajo en Windows.
Una función de tejón de miel, que simplemente no se preocupa por las condiciones de carrera, pero funciona multiplataforma.
function safeCopy($src, $dest) {
if (is_file($dest) === true) {
// if the destination file already exists, it will NOT be overwritten.
return false;
}
if (copy($src, $dest) === false) {
echo "Failed to copy $src... Permissions correct?\n";
return false;
}
return true;
}
- 1. Cómo creo un archivo en python sin sobreescribir un archivo existente
- 2. JavaScript: Agregar un controlador onClick sin sobreescribir el existente
- 3. java.io.FileNotFoundException en un archivo existente
- 4. GIT: ¿Cómo verificar un archivo de una confirmación previa sin sobreescribir la actual?
- 5. ¿Cómo serializar en un archivo existente?
- 6. Copiar archivos sin sobreescribir
- 7. Javascript: cargando un archivo ... sin un archivo
- 8. Evite que se sobrescriba el contenido de un archivo existente al escribir en un archivo
- 9. Manipular un archivo en la memoria con PHP (sin crear un archivo temporal en el disco)
- 10. Descarga del archivo .zip se ejecuta un archivo dañado php
- 11. Cómo devolver un archivo en PHP
- 12. ¿Cómo puedo indicarle a Perforce que se fusione en lugar de sobreescribir o revertir cuando deshace un archivo?
- 13. ¿Cómo escribir en un archivo en PHP?
- 14. Cómo duplicar un archivo PHP con PHP
- 15. ¿Cómo ver un archivo escribir en PHP?
- 16. ¿Cómo reemplazar una cadena en un archivo existente en Perl?
- 17. Guardar salida de un archivo php en un archivo html
- 18. Cómo borrar el texto existente en un archivo
- 19. Actualización de un archivo Rdata existente
- 20. escritura a un Excel archivo existente
- 21. ¿Cómo se duplica un archivo en XCode?
- 22. ¿Cómo se copia un archivo en SharePoint utilizando un servicio web?
- 23. creando un archivo zip en php sin usar ziparchive
- 24. Importe un proyecto Git existente en Eclipse sin un archivo .project
- 25. ¿Cómo elimino un archivo del control de versiones svn sin eliminarlo de cada copia de trabajo?
- 26. Copia de archivos desde un directorio en un directorio existente
- 27. ¿Cómo tener diferentes soluciones se refieren a un archivo resx?
- 28. ¿Cómo modificar el archivo Excel existente usando PHP?
- 29. Eliminar un archivo existente de un Git Repo
- 30. ¿Por qué "Copiar si es nuevo" no copia un archivo cuando se actualiza el archivo?
Aún tiene una condición de carrera. Pero estás en el camino correcto: si el fopen tiene éxito, utiliza fwrite() para realizar la copia y desvincula el archivo de origen cuando se complete. –