代码之家  ›  专栏  ›  技术社区  ›  Chris Bier

PHP图像调整大小和我的上载脚本

  •  1
  • Chris Bier  · 技术社区  · 15 年前

    我看过很多例子,但我不确定它如何与我目前拥有的上传脚本联系在一起。有人能解释一下我是如何使用ImageMagick或类似的工具在保持w:h比率的同时将上传的图像调整到固定宽度的吗?

    我在谷歌上搜索并浏览了150多个网页,但没有一个网页能真正给出一个我认为适合我的情况的例子。任何帮助都将不胜感激。这是我的代码:

    // Include Extension finder function.
    include_once 'find_extension.php';
    
        // Function Gathers the Input Name, Store Number and Picture Number. The picture number is assigned by the loop that will be cycling through the images to be uploaded. The store Number and the Picure Number will make the file name.
        function uploadImage($inputname, $storenum, $picturenum){
    
    // A few parameters, to restrict file types and file size to 20kb.
    if ((($_FILES[$inputname]["type"] == "image/gif")
    || ($_FILES[$inputname]["type"] == "image/png") 
    || ($_FILES[$inputname]["type"] == "image/jpeg") 
    || ($_FILES[$inputname]["type"] == "image/pjpeg"))
    && ($_FILES[$inputname]["size"] < 200000))
      {
          // If there is an error, echo the error, if not continue.
        if ($_FILES[$inputname]["error"] > 0){
            echo "Error: " . $_FILES[$inputname]["error"] . "<br />";
        }else{
          // Echo out File information.
     /* echo "Upload: " . $_FILES[$inputname]["name"] . "<br />";
      echo "Type: " . $_FILES[$inputname]["type"] . "<br />";
      echo "Size: " . ($_FILES[$inputname]["size"] / 1024) . " Kb<br />";
      echo "Stored in: " . $_FILES[$inputname]["tmp_name"]; */
        }
    
        // Get the extension so we can rename using the previous function.
        $ext = findexts($_FILES[$inputname]["name"]);
    
        $newpicturename = $storenum . $picturenum . "." . $ext;
        // Check to see if the file exists, if it does then tell the user. If not continue.
        if (file_exists("userimages/" . $newpicturename)){
    
          echo "<br>" . $newpicturename . " already exists. ";
    
          }else{
    
        // Uploads the file.
          move_uploaded_file($_FILES[$inputname]["tmp_name"], "userimages/" . $newpicturename);
    
        $picturefield = "picture" . $picturenum;
        $picturepath = "userimages/" . $newpicturename;
        //Inserts data into ad DB
        mysql_query("UPDATE storead SET $picturefield='$picturepath' WHERE storenum='$storenum'");
        // Tells the User.
         // echo "Stored in: " . "userimages/" . $newpicturename;
          }
    
      }else{
          // If the upload does not meet the parameters above, then tell the user and cancel.
          echo "Error uploading " . $_FILES[$inputname]["name"] . ". File may be too large or of unnacepted format.";
      }
    
    }
    

    谢谢:

    3 回复  |  直到 14 年前
        1
  •  3
  •   Community CDub    8 年前

    不是移动上传的文件(),而是将文件加载到图像处理库中,调整其大小,然后将其保存。

    例如,使用gd,从imagecreatefromgif()、imagecreatefromjpeg()或imagecreatefrompng()开始(取决于您使用的格式),然后使用imagecreatetruecolor()创建所需缩略图大小的新图像,并使用imagecopyresampled()将原始图像调整为该图像。最后,根据需要的格式,使用imagegif()/imagejpeg()/imagepng()保存结果。

    如果您只需要一个固定的宽度,同时保持纵横比,那么确定目标大小非常容易:新的_高度=圆形的_到_整个_像素(新的_宽度*原始的_高度/原始的_宽度)。不过,值得做一些健康检查:比如说有人上传了1X2000像素的图像。目标宽度为(比如)200像素,然后将其放大到200x400000,这是一个巨大的图像,可能会占用服务器的所有内存!所以也要有一个最大高度。

    最后,您的脚本本身包含太多严重的安全漏洞,无法列出。在将类似的东西放到公共互联网上之前,您需要了解目录遍历攻击、SQL注入、HTML注入(XSS)和文件上载类型嗅探漏洞(例如,将javascript嵌入伪装为图像文件的HTML中)。

    埃塔:

    你认为这个网站覆盖了大部分的基地吗?

    不完全是,但这是一个开始。这个建议:

    当您将任何上载的文件放入上载文件夹时,请将该文件重命名为一些随机名称,并跟踪数据库中的文件名。

    非常重要。不能信任用户提交的文件名。文件名比你想象的要复杂,即使它们不是恶意的,文件名也有很多奇怪的错误之处:

    • 有些浏览器提交文件leafnames、一些完整路径,而您不知道客户机上文件路径的格式(各种平台上的目录分隔符包括/、\、:、。可能还有其他人)。

    • 如果给定的文件名包含不允许使用的字符,会发生什么情况?控制字符?Unicode字符?

    • 如果你在一个Windows服务器上,试着用一些看起来无害但保留的名称(如com)创建文件,你会得到一个裁剪器。此外,Windows会以一种容易混淆脚本的方式,静默地丢弃尾随的空格和点。

    后者是您链接的脚本中潜在的安全漏洞。它检查文件名末尾是否有.php等错误的文件扩展名。但是,如果您将一个名为x.php(带有空格)的文件上载到Windows服务器,它会很高兴地接受该文件并将其保存为x.php。(脚本中也有一个bug,正如它使用的那样。在表示任何字符的正则表达式中。因此,文件名poo.pottophp将被视为具有.php扩展名。)

    像往常一样,白名单优于黑名单。只允许.jpeg扩展比不允许已知的坏扩展更有可能工作。但是,这仍然不够,因为无法保证提交的jpeg文件实际具有扩展名.jpeg。在Windows上,它可能有一个扩展名.jpg或.pjpeg或其他完全映射到客户机上的jpeg的东西。在Mac或Linux上,它可能根本没有文件扩展名!

    综上所述:最好忽略任何与文件上载字段一起提交的文件名/路径。也许你可以看看它来猜测如果你不知道文件可能是什么格式,但你不能依赖它,你永远不应该接受用户的话,并实际保存它的名字。

    这个页面也不包括我提到的伪装成图像文件的HTML。如果您允许任何人上传您不完全信任的文件,并且完全可以访问您站点上的所有内容,那么您需要为此担心。你可以读到它 here . 请参阅有关PHP文件上载脚本风险的更多讨论 here .

    EtA2:

    我看到了很多关于上传到网络目录上的建议。然而,我的脚本仍然会向网站的访问者显示这些文件。

    是的,那是个很好的开始。通过将服务过程控制在自己的手中,您可以避免Web服务器以意外的方式处理文件类型出现任何问题,您可以使用自己已知的安全文件名,并且通过让脚本添加内容处置:附件头,您可以主要防止浏览器将活动内容(如javascript)视为源代码。从站点的安全上下文,导致跨站点脚本问题。

    这种方法的缺点是通过php提供文件服务非常多, 许多的 比让Web服务器做的慢。你可以通过在你的文件服务脚本中实现一个HTTP缓存头文件的负载来改善问题,但是这是一个很大的工作,而且它仍然不会像一个用C语言编写的典型Web服务器那样快,并且可能使用内核级的网络效率黑客。对于你偶尔提供的文件,这没问题。对于一个在繁忙的网站上一直被浏览的流行图片来说,这一点都不好。

    另外,以前也有一些问题,Flash会忽略内容处置头,这仍然会导致通过该插件向XSS发送秘密文件。现在这些都已经修复了,但是谁知道还有其他插件和奇怪的浏览器行为。因此,为了安全起见,最好是为不受信任的用户提供来自不同主机名的上传文件,例如data.example.com之类的子域。这将阻止跨两个安全上下文泄漏cookie和身份验证详细信息。如果您使用基于Web服务器的方法来吐出文件,您肯定需要采取这种预防措施。

    我只想把事情办好,太复杂了

    是的,这看起来像一个看似简单的任务,但实际上不是。一些知名度很高的网站由于不可信的上传而出现了安全问题;如果微软和谷歌的网络伙伴不能总是正确的进行上传,很可能 相当复杂…

    它没有帮助(像对PHP一样)99%的教程覆盖了这类东西是完全的废话。

        2
  •  1
  •   searlea    15 年前
    list($originalWidth, $originalHeight) = getimagesize($originalFile);
    $width = 250; // whatever your fixed width is
    $height = ceil(($width / $originalWidth) * $originalHeight);

    然后按照鲍勃的指示

        3
  •  1
  •   grimman    15 年前
    // Get the image data.
    // This REALLY needs some form of security, doing it like in this example is *bad*.
    // There are other functions than "imagecreatefromjpeg" to handle other formats.
    $image = imagecreatefromjpeg($_FILES["userfile"]["tmp_name"]);
    
    // Get image dimensions.
    $imgX = imagesx($image);
    $imgY = imagesy($image);
    
    // Get aspect ratio.
    // Biggest dimension is what we will use to constrain the thumbnail.
    if($imgX > $imgY) {
        $multiplier = 150 / $imgX;
    } else {
        $multiplier = 150 / $imgY;
    }
    
    // Create a scaled down version of the uploaded image.
    $thumb = imagecreatetruecolor($imgX * $multiplier, $imgY * $multiplier);
    imagecopyresampled($thumb, $image, 0,0,0,0, $imgX * $multiplier, $imgY * $multiplier, $imgX, $imgY);
    

    评论太多了!这大概就是我在自己的图库中创建缩略图时使用的代码。 我能看到的唯一问题是,在最大尺寸中,是否需要将缩略图设置为非正方形,因为此代码仅约束为正方形。