1

我看过很多例子,但我不确定它如何与我目前拥有的上传脚本联系起来。有人可以解释一下我如何能够使用 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.";
  }

}

谢谢 :)

4

3 回答 3

3

不是 move_uploaded_file(),而是将文件加载到图像处理库中,调整大小,然后保存。

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

如果您只想要一个固定宽度同时保持纵横比,那么确定目标大小非常容易:new_height= round_to_whole_pixels(new_width*original_height/original_width)。但是值得进行一些健全性检查:假设有人上传了 1x2000 像素的图像。以(比如说)200 像素的宽度为目标,然后您会将其放大到 200x400000,这是一个可能会占用您所有服务器内存的巨大图像!所以也有一个 max_height 。

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

预计到达时间:

你认为这个网站涵盖了大多数基础吗?

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

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

非常重要。您永远不能信任用户提交的文件名。文件名比你想象的要复杂,即使它们不是恶意的,文件名也有很多奇怪的方式可能出错:

  • 一些浏览器提交文件叶子名称,一些完整路径,并且您不知道客户端计算机上文件路径的格式(各种平台上的目录分隔符包括'/','\',':','.',可能还有其他) .

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

  • 如果您使用的是 Windows 服务器,请尝试使用看起来无害但保留名称(例如“com”)创建文件,您会遇到麻烦。此外,Windows 以一种很容易混淆您的脚本的方式默默地丢弃尾随空格和点。

后者是您链接的脚本中的潜在安全漏洞。它检查文件名末尾的“坏”文件扩展名,如“.php”。但是,如果您将一个名为“x.php”(带有空格)的文件上传到 Windows 服务器,它会很乐意接受它并将其保存为“x.php”。(脚本中还有一个错误,因为它在正则表达式中使用 '.',它代表任何字符。因此文件名 'poo.potatophp' 将被视为具有 .php 扩展名。)

像往常一样,白名单比黑名单更好。只允许例如。'.jpeg' 扩展比禁止已知的坏扩展更有可能起作用。但是,这仍然不够,因为不能保证提交的 JPEG 文件实际上具有扩展名“.jpeg”。在 Windows 上,它可能具有扩展名“.jpg”或“.pjpeg”或其他完全恰好映射到客户端计算机上的 JPEG 的内容。在 Mac 或 Linux 上,它可能根本没有文件扩展名!

所以总结一下:最好忽略任何与文件上传字段一起提交的文件名/路径。如果您还不知道,也许您可​​以看一下它以猜测文件可能是什么格式,但是您不能依赖它,而且您永远不应该相信用户的话并实际将其保存在该格式下姓名。

该页面也没有涵盖我提到的“伪装成图像文件的 HTML”案例。如果您允许任何人上传您不完全信任的文件,并且可以完全访问您网站上的所有内容,那么您需要担心这一点。你可以在这里阅读。在此处查看有关 PHP 文件上传脚本风险的更多讨论。

ETA2:

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

是的,这是一个很好的起点。通过将服务过程控制在您自己手中,您可以避免网络服务器以意想不到的方式处理文件类型的任何问题,您可以使用自己的已知安全文件名,并让您的脚本添加“Content-Disposition:附件”标题,您主要可以防止浏览器将 JavaScript 等活动内容视为源自您站点的安全上下文,从而导致跨站点脚本问题。

这种方法的缺点是通过 PHP 提供文件比让 Web 服务器提供文件要慢得多您可以通过在文件服务脚本中实现大量 HTTP 缓存标头内容来改善问题,但这需要大量工作,而且它仍然不会像用 C 编写的典型 Web 服务器那样快,并且可能使用内核级网络效率黑客。对于您偶尔提供的文件,这没问题。对于在繁忙的网站上一直查看的流行图像,这根本没有好处。

此外,曾经存在一些问题,即 Flash 会忽略 Content-Disposition 标头,这仍然可能导致通过该插件将偷偷摸摸的文件发送到 XSS。这些现在已修复,但谁知道可能还有其他插件和奇怪的浏览器行为。因此,为了安全起见,最好从不同的主机名提供您不受信任的用户上传的文件,例如。像 data.example.com 这样的子域。这可以阻止 cookie 和身份验证详细信息在两个安全上下文中泄漏。如果您采用基于网络服务器的方式来吐出文件,那么您肯定需要采取这种预防措施。

我只是想完成这件事,它太复杂了

是的,这看起来像是一项看似简单的任务,但实际上并非如此。由于不受信任的上传,一些非常知名的网站遇到了安全问题;如果微软和谷歌的网络人不能总是把它弄好,那可能相当复杂的......

这无济于事(与 PHP 一样)99% 的涵盖此类内容的教程都是完全废话。

于 2009-08-19T22:48:03.333 回答
1
list($originalWidth, $originalHeight) = getimagesize($originalFile);
$width = 250; // whatever your fixed width is
$height = ceil(($width / $originalWidth) * $originalHeight);

然后按照鲍勃的指示

于 2009-08-19T22:53:53.367 回答
1
// 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);

评论海量!这大致是我用来在我自己的画廊中创建缩略图的代码。我能看到的唯一问题是,如果您需要缩略图的最大尺寸不是正方形,因为此代码仅限制为正方形。

于 2009-08-20T07:49:45.617 回答