【问题标题】:read single byte from PHP uploaded file从 PHP 上传的文件中读取单个字节
【发布时间】:2011-04-11 01:20:22
【问题描述】:

我对 PHP 很陌生,所以请原谅我的无知。

我有 HTML 供上传:

<form action="upload.php" method="post" enctype="multipart/form-data">
<label for="file">Filename:</label>
<input type="file" name="file" id="file" /><br />
<input type="submit" name="submit" value="Submit" />
</form>

我的 PHP 是(它不知道,但希望它能显示我想要的):

<?php
if ($_FILES["file"]["error"] > 0)
  {
  echo "Error: " . $_FILES["file"]["error"] . "<br />";
  }
else
  {
  $content = fread($_FILES["file"],10);
  echo $content;
  echo "byte10 is: " ???
  }
?>

我想:从这个上传的文件中,我想读取一个字节(比如字节 10)。我想打印出这个字节的 ascii (HEX) 代码。我怎么做?我需要将文件保存到服务器吗?

(不切实际的目标是加密文件并将加密的文件发送回用户。所以我想 (1) 上传文件 (2) 读取每个单独的字节 (2) 执行加密字节级(3)保存文件并发回给用户)

【问题讨论】:

    标签: php file-upload readfile fread


    【解决方案1】:

    多个实现,我会给你一个可重复使用的,使用fseek

    <?php
    function getByte($f,$n){
        fseek($f,$n);
        return fread($f,1);
    }
    
    $f=fopen('your_file_path');
    echo getByte($f,10);
    ?>
    

    我强烈建议在使用任何 $_FILES 之前使用 move_uploaded_file

    附:如果您不小心,这可能会变得非常非常昂贵,我对您的建议是读取更大的块,然后对它们执行操作。

    【讨论】:

    • 感谢您的回复!那么 move_uploaded_file 将文件移动到服务器并在那里保存副本?如果是,是否有办法只提取信息而不将文件保存在服务器上?
    • 没有。不会。当用户上传文件时,文件会保存在临时目录中。由于各种原因,您必须使用 move_uploaded_file 移动它。您可以将 move_uploaded_file 视为一个非常特殊的复制文件功能。
    • 好的,所以 move_uploaded_file 只是从临时文件夹移动到以某种方式保存在“内存”中的“特殊副本”?
    • 你看过……函数吗?它将文件从临时目录移动到另一个目录。
    • 好的,我从手册中看到,必须在服务器上指定一个位置才能移动文件。所以这实际上将文件“保存”在服务器上(?)有没有办法绕过实际将文件保存在服务器上? (抱歉这里有点慢……)
    【解决方案2】:

    非常感谢您的“最终目标”——它将帮助我们确保您不会无意中做出愚蠢的事情。

    加密是一个非常复杂的话题。您不应该编写自己的加密例程。使用完整的预构建解决方案。

    Mcrypt 是 PHP 最好的加密扩展。 Mcrypt 支持multiple common ciphers,包括 AES(“Rijndael”)。 Encryption is pretty darn easy -- 使用 "CBC" mode 作为您的文件。


    Vigenère cipher 是一个 460 年前的替换密码,基于一个简单的查找表。

    这解释了整个一次一个字符的事情。

    虽然您可以一次读取整个文件一个字节,但您可能会发现使用字符串更方便。您可以将整个文件读入一个变量(通过file_get_contents 或其他),然后使用substrthe square bracket substring syntax 一次读取一个字节的字符串。请记住,PHP 字符串只是简单的字节列表。

    鉴于$data是文件中完整的数据,你可以这样处理每个字节:

    $length = strlen($data);
    for($i = 0; $i < $length; $i++) {
        $byte = $data[$i];
    // Or
        $byte = substr($data, $i, 1);
    // Process the byte here.
    }
    

    这仅适用于小文件(小于几兆字节),因为它需要将整个文件加载到内存中。

    我想打印出这个字节的 acscii (HEX) 代码

    您可以使用ord 获取十进制 值,然后使用dechex 将其转换为十六进制字符串:

    $hex_value = dechex(ord($byte));
    

    后替换,你可以颠倒它——使用hexdec从十六进制到十进制,然后chr从十进制到字节:

    $converted_byte = chr(hexdec($ciphered_hex));
    

    【讨论】:

    • 感谢您的回复。加密部分更多是为了好玩。我想使用 vigenere 密码加密文件,并想尝试手动完成所有操作。 (但我肯定会尝试研究这个 Mcrypt)
    • @Thomas,只要你明白加密真实数据是最适合别人的代码的东西,那么无论如何,去吧!我稍后会为您更新我的答案,并为您提供替代解决方案。
    • @Thomas,我的答案现已更新,提供了有关处理数据的更多信息,以及如何获取十六进制并返回。
    • 太棒了!我认为这正是我所需要的。所以正如艾伦·汉密尔顿在下面写的那样,我只需执行 "$content = fread($_FILES["file"],??); 将所有内容作为字符串,然后处理该字符串。那么,如果文件“大”,我该怎么办? (我只是想让它适用于可能低于 5MB 的文件)
    • 好的,所以“$content = fread($_FILES["file"],int);”有些东西不起作用,这就是我开始的......我想我必须在服务器上保存文件的副本以便能够对内容执行任何操作,对吗?
    【解决方案3】:

    在 PHP 中,字符串基本上是一个字节数组,因此您可以使用 fread() 函数将一些字符读入字符串,然后使用数组表示法访问各个字节。例如。

    $content = fread($_FILES["file"],10);
    echo $content;
    echo "byte10 is: ".$content[9]; // 9 because offset starts from 0
    

    【讨论】:

    • 感谢您的回复。这实际上可能是我正在寻找的。所以这将文件的前 10 个字节保存在一个字符串中,我可以读取该字符串的最后一个字节(?)。所以我也可以将整个文件读入一个字符串,然后逐字节处理该字符串,这样我就不必在服务器上保存任何内容,对吧?
    • 当然,如果文件很小,您可以将整个文件读入内存。对于较大的文件,您可以使用 fread() 将多个字节读入缓冲区。该手册有一个使用 while 循环和 feof() 的示例php.net/manual/en/function.fread.php
    猜你喜欢
    • 2013-07-09
    • 2011-01-13
    • 2020-06-12
    • 1970-01-01
    • 1970-01-01
    • 2017-11-02
    • 2019-02-14
    • 1970-01-01
    相关资源
    最近更新 更多