我正在建立一个基于网络的系统,它将承载高负荷图像的负载和负载,并且它们将可供出售。当然我永远不会显示高分辨率图像,而是在浏览时人们只能看到低分辨率的水印图像。目前工作流程如下:
PHP脚本处理高图像上传,上传图像时,它会自动调整为低分辨率图像和缩略图图像,并且两个文件都保存在服务器上(不添加水印) 。
当人们浏览时,页面会显示图像的缩略图,点击后,它会放大并显示带有水印的低图像。当我打开低位图像时,我会立即应用水印。
我的问题是,正确的方法是什么:
1)我是否应该使用缩略图保存第二张低照片副本,只有在第一次访问时?我的意思是如果有人访问图像,我会动态添加水印,然后显示图像&将其存储在服务器上。如果存在水印副本,则下次访问相同图像时只显示wm副本,否则即时应用水印。 (如果更改了watermark.png,只需删除加水印的图像,它们将被重新创建为访问过)。
2)我应该像现在一样继续使用水印。
我最大的问题是PHP file_exists()
与为图像添加水印之间的差异有多大,例如:
$image = new Imagick();
$image->readImage($workfolder.$event . DIRECTORY_SEPARATOR . $cat . DIRECTORY_SEPARATOR .$mit);
$watermark = new Imagick();
$watermark->readImage($workfolder.$event . DIRECTORY_SEPARATOR . "hires" . DIRECTORY_SEPARATOR ."WATERMARK.PNG");
$image->compositeImage($watermark, imagick::COMPOSITE_OVER, 0, 0);
所有低级图像均为1024x1024,JPG,质量设置为45%,并且删除了所有不必要的滤镜,因此低图像的文件大小约为40Kb-80Kb。
它与this question有某种关系,只是规模和情景略有不同。
我在一个专用服务器(Xeon E3-1245v2)cpu,32 GB ram,2 TB存储空间),该网站整体流量不大,但它不时有巨大的峰值。当图像发布时,我们每小时可以获得几千次点击,人们可以通过图像浏览,下载,购买等等。因此,在正常使用情况下,我确信即时生成是正确的方法,我有点担心关于穗期。
需要提一下,我正在使用ImageMagick库进行图像处理,而不是GD。
感谢您的意见。
更新
没有一个完整解决方案的答案,但这是好事,因为我从来没有寻找过。这是一个艰难的决定,哪一个接受谁和谁给予赏金。
@ Ambroise-Maupate解决方案很好,但它继续在PHP上完成这项工作。
@Hugo Delsing建议使用Web服务器来提供缓存文件,降低对PHP脚本的调用,这意味着使用更少的资源,另一方面,它不是真正的存储友好。
我将使用2个答案的混合合并解决方案,在CRON作业上转发以删除垃圾。
感谢您的指示。
答案 0 :(得分:5)
我建议您即时创建水印图像,并在每个人建议的同时缓存它们。
然后,您可以创建一个垃圾收集器 PHP脚本,该脚本将每天执行(使用 cron )。此脚本将浏览您的缓存文件夹以读取每个图像访问时间。这可以使用fileatime()
PHP方法完成。然后,当在24或48小时内未访问缓存的 wm 图像时,只需将其删除即可。
使用此方法,您可以处理 spike 期间,因为第一次请求时会缓存图像。并且您将节省您的硬盘空间,因为您的垃圾收集器脚本将为您删除未使用的图像。
此方法仅在您的服务器分区启用 atime 更新时才有效。
答案 1 :(得分:4)
我个人会在CDN中创建一个静态/无cookie的子域来处理这类图像。主要原因是:
第一步是在子域上创建一个指向空文件夹的网站。使用IIS / Apache或其他任何设置来禁用此新网站的会话。还要在网站上设置一些长缓存标头,因为内容不应更改
第二步是创建一个包含以下内容的.htaccess
文件。
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*) /create.php?path=$1 [L]
这将确保如果有人访问现有图像,它将直接显示图像而不会PHP
干扰。每个不存在的请求都将由create.php
脚本处理,这是您应该添加的下一个内容。
<?php
function NotFound()
{
if (!headers_sent()) {
$protocol = (isset($_SERVER['SERVER_PROTOCOL']) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0');
header($protocol . ' 404 Not Found');
echo '<h1>Not Found</h1>';
exit;
}
}
$p = $_GET['path'];
//has path
if (strlen($p)<=1)
NotFound();
$clean = explode('?', $p);
$clean = explode('#', $clean[0]);
$params = explode('/', substr($clean[0], 1)); //drop first /
//I use a check for two, because I dont allow images in the root folder
//I also use the path to determine how it should look
//EG: thumb/125/90/imagecode.jpg
if (count($params)<2)
NotFound();
$type = $params[0];
//I use the type to handle different methods. For this example I only used the full sized image
//You could use the same to handle thumbnails or cropped/watermarked
switch ($type) {
//case "crop":if (Crop($params)) return; else break;
//case "thumb":if (Thumb($params)) return; else break;
case "image":if (Image($params)) return; else break;
}
NotFound();
?>
<?php
/*
Just some example to show how you could create a responds
Since you already know how to create thumbs, I'm not going into details
Array
(
[0] => image
[1] => imagecode.JPG
)
*/
function Image($params) {
$tmp = explode('.', $params[1]);
if (count($tmp)!=2)
return false;
$code = $tmp[0];
//WARNING!! SQL INJECTION
//USE PROPER DB METHODS TO GET REALPATH, THIS IS JUST EXAMPLE
$query = "SELECT realpath FROM images WHERE Code='".$code."'";
//exec query here to $row
$realpath = $row['realpath'];
$f = file_get_contents($realpath);
if (strlen($f)<=0)
return false;
//create folder structure
@mkdir($params[0]);
//if you had more folders, continue creating the structure
//@mkdir($params[0].'/'.$params[1]);
//store the image, so a second request won't access this script
file_put_contents($params[0].'/'.$params[1], $f);
//you could directly optimize the image for web to make it even better
//optimizeImage($params[0].'/'.$params[1]);
//now serve the file to the browser, because even the first request needs to show the image
$finfo = finfo_open(FILEINFO_MIME_TYPE);
header('Content-Type: '.finfo_file($finfo, $params[0].'/'.$params[1]));
echo $f;
return true;
}
?>
答案 2 :(得分:1)
对于大多数情况,懒洋洋地应用水印可能最有意义(在请求时动态生成带水印的图像然后缓存结果)但是如果你有需求大的尖峰你自己创建一个DOS机制:创建上传水印版本。
答案 3 :(得分:0)
考虑您的HDD存储容量和Pikes。
如果被查看,我只会创建一个带水印的图像。(所以是动态的)这样你就不会在很多空间中使用一堆可能被查看过的文件。
我不会水印缩略图我宁愿制作一个假水印的过滤器,以防止被保存。该过滤器将应用于所有缩略图,而不会创建第二个图像。
通过这种方式,所有的缩略图都会加水印(在顶部使用onther元素伪造)。
然后,如果查看其中一个缩略图,则会生成带水印的图像(仅一次),因为在生成之后,您将加载新的水印图像。
这将是处理硬盘存储和Pikes的最有效方式。
另一种选择是升级您的托管服务。 Godaddy提供无限存储和带宽,每年约50美元。