2008-10-22 9 views

Répondre

8

La solution évidente serait d'appeler file_exists pour vérifier si le fichier existe, mais cela pourrait provoquer une condition de concurrence. Il est toujours possible que l'autre fichier soit créé entre lorsque vous appelez file_exists et lorsque vous appelez copy. Le seul moyen sûr de vérifier si le fichier existe est d'utiliser fopen.

Lorsque vous appelez fopen, définissez le mode sur 'x'. Cela indique fopen pour créer le fichier, mais seulement s'il n'existe pas. S'il existe, fopen échouera et vous saurez que vous n'avez pas pu créer le fichier. Si cela réussit, vous aurez créé un fichier à la destination que vous pouvez copier en toute sécurité. Exemple de code est ci-dessous:

// 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; 
} 
+0

Vous avez toujours une condition de concurrence. Mais vous êtes sur la bonne voie - si la fopen réussit, utilisez fwrite() pour effectuer la copie, et délier le fichier source une fois terminé. –

3

Je pense que vous avez répondu à votre propre question - vérifiez que le fichier de destination existe avant d'effectuer la copie. Si le fichier existe, ignorez la copie.

Mise à jour: Je vois que vous avez vraiment répondu à votre propre question. Vous mentionnez les conditions de course, mais si vous trouvez que le fichier existe déjà, comment savez-vous que:

  • le fichier qui est déjà là est vraiment celui que vous voulez copier
  • l'autre processus de copier le fichier a terminé son travail (les données de fichier est tout ce qu'il ya)
  • l'autre copie de processus, le fichier ne va pas à l'échec (et laisser un dossier incomplet, ou supprimer le nouveau fichier)

Je pense que vous devrait considérer ces questions en concevant une solution à votre problème.

0

Essayez d'utiliser la fonction link() au lieu 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; 
    } 
} 

Malheureusement, cela ne travail sous Windows.

0

Une fonction de blaireau de miel, qui ne se soucie pas des conditions de course, mais travaille multi-plateforme.

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; 
} 
Questions connexes