PHP在文件(而不是文件名)上使用getimagesize()


PHP using getimagesize() on a file (not a file name)

我正在为我的网站制作一个附件系统。在基于表单的上传方法中,您可以使用获取图像大小

$SizeResult = getimagesize($_FILES['file']['tmp_name']);

但是使用Drag&通过HTML5的文件API的Drop上传系统,文件上传不是通过表单张贴,而是通过黑魔法&魔法。

$File = file_get_contents('php://input');

在这种情况下,$File不是名称,而是文件的实际二进制内容。

当getimagesize()似乎只接受文件名称时,我如何获得所述$File的大小?在内部,getimagesize希望从磁盘本身打开文件。它不想接受$File。

有人知道我该怎么解决这个问题吗?我希望避免将文件保存到磁盘。

这就是我的意思,请尝试一下:

$File = file_get_contents('php://input');
$image = ImageCreateFromString($File);
echo ImageSX($image); // width
echo ImageSY($image); // height

我制定了一个我认为最好的解决方案。我必须承认,使用getimagesize()函数的主要原因是获取文件的MIME类型(以确保它是图像)。获得大小是一个额外的好处,但我本可以围绕exif_imagetype()函数轻松地提出这个问题。问题是一样的,因为这两个函数都只接受文件名称;而不是文件内容。

所以我所做的基本上是查看PHP源代码,看看exif_imagetype()是如何读取MIME信息的。事实证明,它只读取文件的前12个字节。我复制了它的功能:

function GetConstMimeArray()
{
    // MIME type markers (taken from PHP sourcecode consts in 'ext'standard'image.c starting at line 39).
    return array
    (
        'gif' => array(ord('G'), ord('I'), ord('F')),
        'psd' => array(ord('8'), ord('B'), ord('P'), ord('S')),
        'bmp' => array(ord('B'), ord('M')),
        'swf' => array(ord('F'), ord('W'), ord('S')),
        'swc' => array(ord('C'), ord('W'), ord('S')),
        'jpg' => array(0xff, 0xd8, 0xff),
        'png' => array(0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a),
        'tif_ii' => array(ord('I'), ord('I'), 0x2a, 0x00),
        'tif_mm' => array(ord('M'), ord('M'), 0x00, 0x2a),
        'jpc' => array(0xff, 0x4f, 0xff),
        'jp2' => array(0x00, 0x00, 0x00, 0x0c, 0x6a, 0x50, 0x20, 0x20, 0x0d, 0x0a, 0x87, 0x0a),
        'iff' => array(ord('F'), ord('O'), ord('R'), ord('M')),
        'ico' => array(0x00, 0x00, 0x01, 0x00)
    );
}

// Get an array of known MIME headers.
$MimeTypeConsts = GetConstMimeArray();
// Get first 12 bytes of file from stream to do a MIME check.
$File = file_get_contents('php://input', null, null, 0, 12);
if(strlen($File) < 12)
    return;
// Scan first 12 bytes of file for known MIME headers.
$MatchedMime = '';
foreach($MimeTypeConsts as $Type => $Bytes)
{
    $NumMatching = 0;
    $NumBytes = count($Bytes);
    for($i = 0; $i < $NumBytes; $i++)
    {
        if(ord($File[$i]) == $Bytes[$i])
            $NumMatching++;
        else
            break;
    }
    if($NumMatching == $NumBytes)
    {
        $MatchedMime = $Type;
        break;
    }
}
// Check if the file does NOT have one of the known MIME types.
if(strlen($MatchedMime) <= 0)
    return;
// If we fix up TIF_TT and TIF_MM, you can use $MatchedMime in lieu
// of the extension on the file name.
if($MatchedMime == 'tif_ii' || $MatchedMime == 'tif_mm')
    $MatchedMime = 'tif';
// What's the max size allowed to upload?
$MaxSize = min(ReturnBytes(ini_get('post_max_size')), MAX_UPLOAD_SIZE);
// Get full file.
$File = file_get_contents('php://input', null, null, 0, $MaxSize + 8);
// Get file size.
$Size = strlen($File);
if($Size > $MaxSize)
    return;
// Get hash of the file contents.
$Hash = hash('SHA1', $File, true);
file_put_contents(UPLOADS_DIR.'/'.bin2hex($Hash).'.'.$MatchedMime, $File);

该文件现在将保存在UPLOADS_DIR中,使用哈希作为其名称,使用MIME类型作为其扩展名。(无论文件名最初的扩展名是什么,都会被忽略而不使用。)

希望这能帮助

<?php
list($width, $height, $type, $attr) = getimagesize("img/flag.jpg");
echo "<img src='"img/flag.jpg'" $attr alt='"getimagesize() example'" />";
?>