【问题标题】:integrity of copy function in phpphp中复制功能的完整性
【发布时间】:2018-03-13 21:55:15
【问题描述】:

我有一个从 SD 卡中提取照片的应用。复制后,卡片将被重新格式化并放回相机中,并且将存储更多照片。

目前,我不使用 PHP copy() 函数,而是(大致)执行以下操作:

$card = '/Volumes/SD_Card/DCIM/EOS/';
$files = scandir($card);
$target = '/Volumes/HARD_DRIVE/photos/';

foreach($files as $k => $file) {
    if( strtolower ( pathinfo($file,PATHINFO_EXTENSION) ) == 'jpg') {
        $img_data = file_get_contents($file);
        $orig_md5 = md5($img_data);

        $success = file_put_contents($target . $file, $img_data);
        unset ($img_data);

        if( $success != TRUE ) {
            echo "an error occurred copying $file\n"; exit;
        } elseif ( $orig_md5 != md5_file($target . $file) ) {
            echo "an error occurred confirming data of $file\n"; exit;
        } else {
            echo "$file copied successfully.\n";
            unlink ($img_data);
        }
    }
}

我目前正在这样做,因此我可以比较 md5 散列,以确保副本与原件逐位匹配。

我的问题是:

1) 使用 php copy() 会更快吗?我认为它会,因为目标文件不必被读入内存来检查 md5 哈希。

2) 在返回TRUE/FALSE之前,copy() 是否会在函数中进行某种哈希检查以确保副本的完整性?

【问题讨论】:

  • 你也可以用rename()一键移动/删除,为什么觉得功能不靠谱?

标签: php copy md5 md5sum


【解决方案1】:

PHP 的复制功能不仅会更快,而且它使用缓冲区来避免读取内存中所有以前的文件,这对于大文件来说是个问题。返回布尔值仅用于成功写入,您可以依赖它,但如果您想检查哈希使用md5_file 而不是将内容传递给md5,因为它以相同的内存优化方式进行了优化。

但是,如果您只是重命名文件,那么 rename 会好得多,它是完全即时且可靠的。

【讨论】:

  • rename() 是否会在卷之间即时 - 从外部磁盘(SD 卡)到内部硬盘驱动器?
  • 无重命名更像是 Linux 的移动命令。在同一个 HDD 中它是即时的。在其他设备中,它与复制相同。
【解决方案2】:

不,copy() 不执行任何额外的完整性检查,它假定操作系统的文件系统 API 是可靠的。

您可以在源和目标上都使用md5_file()

if (copy($source, $dest) && md5_file($dest) == md5_file($source)) {
    echo "File copied successfully";
} else {
    echo "Copy failed";
}

请注意,您的诚信 cks 实际上并不检查文件是否正确写入磁盘。大多数操作系统使用统一的缓冲区缓存,因此当您在写入文件后立即调用md5_file() 时,它将从内核缓冲区而不是磁盘中获取文件内容。事实上,目标文件可能还没有写入磁盘,它仍然位于等待刷新的内核缓冲区中。 PHP 没有调用sync(2) 的函数,但即使调用了,它仍然会从缓冲区缓存中读取,而不是从磁盘重新读取。

因此,您基本上受操作系统和硬件的支配,您必须假设它们是可靠的。需要更多可靠性测试的应用程序必须执行直接设备 I/O,而不是通过文件系统。

【讨论】:

  • 所以作为一个实际点,如果我正确理解你的评论,我对我编写的代码的结果不会比我只使用copy() 更有信心,而且我正在牺牲性能和几行代码,对吧?
  • 另外,我假设从原始文件存储md5_file() 的输出,然后使用copy() -- 然后一段时间后将原始md5 与md5_file() 的输出进行比较复制的文件将是更可靠的完整性检查 - 因为正如您所提到的,操作系统可能需要一些时间才能将数据写入磁盘?
  • 可能,但您永远无法确定数据何时被其他需要内存的进程推出缓存。
  • 如果你真的需要高完整性,确保它的方法是使用 RAID 磁盘,而不是检查软件。
猜你喜欢
  • 1970-01-01
  • 2017-02-20
  • 2016-03-15
  • 2014-12-14
  • 2013-06-09
  • 1970-01-01
  • 2017-11-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多