Когда вы используете функцию PHP копировать, операция слепо копирует файл назначения, даже если он уже существует. Как безопасно скопировать файл, выполняя копирование только в том случае, если файла нет?






Думаю, вы ответили на свой вопрос - убедитесь, что целевой файл существует, прежде чем копировать. Если файл существует, пропустите копию.
Обновление: я вижу, вы действительно ответили на свой вопрос. Вы упоминаете условия гонки, но если вы обнаружите, что файл уже существует, как вы это узнаете:
Я думаю, вам следует учитывать эти вопросы при разработке решения вашей проблемы.
Очевидным решением было бы вызвать Файл существует, чтобы проверить, существует ли файл, но это может вызвать состояние гонки. Всегда существует вероятность того, что другой файл будет создан между тем, когда вы вызываете Файл существует и когда вы вызываете копировать. Единственный безопасный способ проверить, существует ли файл - использовать fopen.
Когда вы вызываете fopen, установите режим «x». Это говорит fopen создать файл, но только если он не существует. Если он существует, fopen завершится ошибкой, и вы узнаете, что не смогли создать файл. Если это удастся, у вас будет созданный файл в месте назначения, который вы можете безопасно скопировать. Пример кода ниже:
// 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 (!@fclose($file)) {
// There was some problem with our file handle.
return false;
}
// Now we copy over the file we created.
if (!@copy($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;
}
Попробуйте использовать функцию link() вместо 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;
}
}
К сожалению, это нет будет работать в Windows.
Функция медоеда, которая просто не заботится о гоночных условиях, но работает кроссплатформенно.
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;
}
У вас все еще есть состояние гонки. Но вы на правильном пути - если fopen завершится успешно, используйте fwrite () для выполнения копирования и разорвите связь с исходным файлом по завершении.