简体   繁体   中英

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

I am making an attachments system for my website. In a form-based upload method, you can get the image size using:

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

But using a Drag&Drop upload system via HTML5's File API, the files are uploaded not by form post, but by black magic & wizardry.

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

In this case $File is not a name , but the actual binary contents of the file.

How can I get the size of said $File, when getimagesize() only seems to accept file names ? Internally, getimagesize wants to open the file from disk itself. It doesn't want to accept $File.

Anyone know how I can get around this issue? I'm hoping to avoid saving the file to disk.

This is what I meant, please try it:

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

I made a solution that I think is best. I must confess that the primary reason for using the getimagesize() function was to get the MIME type of the file (to ensure it is an image). Obtaining the size is an added bonus, but I could have just as easily framed the question around the exif_imagetype() function. The problem would have been the same, because both functions only accept a file name ; not file contents.

So what I did was basically look in the PHP sourcecode and see how exif_imagetype() read MIME information. It turns out it only reads the first 12 bytes of the file. I replicated its functionality like so:

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)
    );
}

And

// 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);

The file will now be saved in UPLOADS_DIR using the hash as it's name and the MIME type as its extension. (Whatever extension was originally on the file name is ignored and not used.)

Hope this helps

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM