首页 > 解决方案 > 在 CentOS Linux 上以二进制模式写入的疯狂 PHP fopen / fwrite / file_put_contents / move_uploaded_file 错误将 0x0D 添加到每个 0x0A

问题描述

似乎无论我在fopen mode标志中设置什么设置,该文件都会不断将 0x0D 添加到我保存的二进制文件中。

它不仅影响fopen/ fwrite.. 也影响file_put_contents.

file_get_contents我以为是问题一开始.. 但事实证明这个实际上工作正常.. 因为当我使用 bin2hex() 转储文件时,结果很好。

起初我将std::string这个错误归咎于 C++ 中的.. 但事实证明它甚至与 C++ 没有任何关系,但它实际上是 PHP 的错误,或者可能只有 CentOS linux,我还没有找到解决方案将我的文件存储在二进制文件中。我能做的最好的事情是十六进制字符串转储文件。

看看我的代码和截图。

$target_file = "/privatefiles/" . basename($_FILES["a"]["name"]);
$fileTypeExtension = strtolower(pathinfo($target_file,PATHINFO_EXTENSION));

//Check file extension.
if($fileTypeExtension != "dll" && $fileTypeExtension != "exe" ) die("ER");

// Check file size
if ($_FILES["a"]["size"] > 10*(1024*1024)) //10 MB cap
  die("ER");

//To decode a base64 encoded file (this was a quickfix to fix binary file encoding in C++ part).
$fileContent = file_get_contents($_FILES['a']['tmp_name']);
$fileContent = base64_decode($fileContent);

//fail
$fh = fopen("wtf1.bin", "wb");
fwrite($fh, $fileContent, strlen($fileContent));
fclose($fh);

//fail (exact result as top)
$fh = fopen("wtf2.bin", "wb");
$fileContent = bin2hex($fileContent);
for($i=0;$i<strlen($fileContent);$i+=2)
    fwrite($fh, chr(hexdec(substr($fileContent,$i,2))));
fclose($fh);

//good result.. but not binary
$fh = fopen("wtf3.bin", "w");
$fileContent = bin2hex(base64_decode(file_get_contents($_FILES['a']['tmp_name'])));
fwrite($fh, $fileContent);
fclose($fh);

//good result but not binary
file_put_contents($target_file, $fileContent); //good bin2hex.

//fail same as the top 2 fail's.
file_put_contents($target_file."_", file_get_contents($_FILES['a']['tmp_name'])); //bad same as wtf1.bin or wtf2.bin


这是我的屏幕截图(证明运行上面的代码所发生的事情),并使用 C++ 应用程序启动文件上传(不能被窃听,因为起初我使用原始二进制模式发送......然后在这个 0x0D 0x0A 错误之后我改变了它到base64编码来解决传输问题..事实证明这甚至不是问题,但实际上我相信是一个PHP问题..

这是我上传的原始二进制文件(未更改)(如您所见,我在 0x0A 0x40 处停止以向您展示错误)。 原来的

这是相同偏移量的 wtf1.bin (只是 base64_decode 到文件的简单 1 行)。 wtf1

这是相同偏移量的 wtf2.bin (我尝试使用 bin2hex 解决此问题的一些hackery,它可以很好地转储它)。 wtf2

这是 wtf3.bin (bin2hex) 在相同的偏移量下效果很好。(0x846 / 2 = 0x423)(确认相同的偏移量!) wtf3

php版本

即使是这个简单的上传脚本,也会使用 0xA,0xD 上传损坏的文件

<!DOCTYPE html>
<html>
<head>
  <title>Upload your files</title>
</head>
<body>
  <form enctype="multipart/form-data" action="test.php" method="POST">
    <p>Upload your file</p>
    <input type="file" name="uploaded_file"></input><br />
    <input type="submit" value="Upload"></input>
  </form>
</body>
</html>
<?php
  if(!empty($_FILES['uploaded_file']))
  {
    $path = basename( $_FILES['uploaded_file']['name']);
    print_r($_FILES);
    $size = filesize($_FILES['uploaded_file']['tmp_name']);
    echo "<br>size uploaded = " . $size . "<br>";
    if(move_uploaded_file($_FILES['uploaded_file']['tmp_name'], $path)) {
      echo "The file ".  basename( $_FILES['uploaded_file']['name']). 
      " has been uploaded<br>";
      echo "path = " . $path . "<br>";
      echo "size stored = " . filesize($path);
    } else{
        echo "There was an error uploading the file, please try again!";
    }
  }
?>

当我以二进制格式上传这些字节时会发生错误

BC 09 00 00 83 C4 04 BA E8 57 40 00 8D 64 24 00 8A 08 88 0A 40 42 84 C9

我回到服务器

BC 09 00 00 83 C4 04 BA E8 57 40 00 8D 64 24 00 8A 08 88 0D 0A 40 42 84 C9

标签: phpfopenfwriteline-endingsfile-put-contents

解决方案


感谢 CBroe 和 IVO GELOV,问题出在我的 FTP/SFTP 客户端 WinSCP 中。我附上了一个屏幕截图,您需要关闭该设置,这样就不会发生这个问题。

解决了


推荐阅读