我正在使用外部网络服务,该服务将返回我将在我的网站上显示的图片网址,例如:
$url = get_from_web_service();
echo '<img url="'.$url.'" />';
一切正常,除非我有100张图片要显示,然后调用网络服务成为时间&amp;资源消耗。
//the problem
foreach($items as $item) {
$url = get_from_web_service($item);
echo '<img url="'.$url.'" />';
}
所以现在我正在考虑两种选择:
//Option1: Using php get_file_contents():
foreach($items as $item)
{
echo '<img url="url_to_my_website/get_image.php?id='.$item->id.'" />'
}
get_image.php :
$url = get_from_web_service($id);
header("Content-Type: image/png");
echo file_get_contents($url);
//Option2: Using ajax:
echo '<img scr="dummy_image_or_website_logo" data-id="123" />';
//ajax call to the web service to get the id=123 and get the url then add the src attribute to that image.
THOUGHTS
信息
我的问题
由于
答案 0 :(得分:9)
<强>优点:强>
允许自定义标头独立于任何服务器软件。如果您正在使用通常不缓存的内容(例如带有查询字符串的PHP文件),或者将其添加到需要标题功能的软件包中,而不管服务器软件如何,这是一个非常好的主意。
如果您知道如何使用GD或Imagick,则可以轻松调整图像的大小,裁剪,压缩,索引等,以减少图像文件的大小(有时会大幅减少)和使页面加载速度明显加快。
如果将宽度和高度作为变量传递给PHP文件,则可以动态设置尺寸:
<div id="gallery-images">
<noscript>
<!-- So that the thumbnail is small for old mobile devices //-->
<img src="get-image.php?id=123&h=200&w=200" />
</noscript>
</div>
<script type="text/javascript">
/* Something to create an image element inside of the div.
* In theory, the browser height and width can be pulled dynamically
* on page load, which is useful for ensuring that images are no larger
* than they need to be. Having a function to load the full image
* if the borwser becomes bigger isn't a bad idea though.
*/
</script>
对于拥有图片库的网页上的移动用户,这将是非常体贴的。这也是带宽有限的用户非常考虑(就像阿拉斯加的几乎每个人一样。我从个人经验中说出这一点。)
如果用户在网站上传图像,则可以轻松清除图像的EXIF数据。这对于用户隐私以及making sure there aren't any malicious scripts living in your JPGs非常重要。
可以动态创建大型image sprite,并在导致延迟时大幅减少HTTP请求。这是一项很多的工作,所以这不是一个非常强大的专业人士,但你仍然可以使用这种方法,你不能使用第二种方法。
<强>缺点强>:
根据图像的数量和大小,这可能会给您的服务器带来很大压力。当与浏览器缓存一起使用时,动态图像将从缓存中提取而不是重新生成,但是机器人仍然可以很容易地为动态图像提供多次服务。
它需要了解HTTP标头,基本的图像处理技巧,以及如何在PHP中使用图像处理库才能有效。
<强>优点:强>
页面将在任何图像之前完成加载。如果您的内容绝对需要尽快加载,并且图像不是很重要,这一点非常重要。
与任何类型的动态PHP解决方案相比,实现起来要简单,容易且快得多。
它将HTTP请求分开,因此初始内容加载速度更快(因为可以根据浏览器操作而不仅仅是页面加载来发送HTTP请求)。
<强>缺点:强>
它不会减少HTTP请求的数量,只是将它们分开。另请注意,除了所有这些图像之外,还将至少有一个额外的外部JS文件。
如果终端设备(例如较旧的移动设备)不支持JavaScript,则不显示任何内容。解决这个问题的唯一方法是让所有图像在一些<noscript>
标记之间正常加载,这需要PHP生成两倍的HTML。
要求您在页面中添加loading.gif
(以及其他HTTP请求)或Please wait while these images load
文字。我个人认为这对网站用户来说很烦人,因为我希望在页面“完成加载”时看到所有内容。
如果您具备学习如何有效使用方法1的背景知识或时间,那么它提供了更大的潜力,因为它允许在加载后处理页面发送的图像和HTTP请求。
相反,如果您正在寻找一种简单的方法来隔离您的HTTP请求,或者想要通过稍后加载额外的图像来加快内容加载,那么方法2就是您的答案。
回顾方法1和方法2,看起来将两种方法结合使用可能是最好的答案。将两个缓存和压缩的图像与页面一起加载(一个是可见的,另一个是缓冲区,这样用户每次点击“下一个”时都不必等待),并且其余的一个一个地加载一个用户认为合适。
在您的具体情况下,如果您的图片可以以“幻灯片”方式显示,我认为方法2最有效。如果需要立即加载所有图片,尝试压缩它们并使用方法1应用浏览器缓存。如果页面加载上的图像请求太多正在破坏您的速度,请尝试图像spriting。
答案 1 :(得分:3)
截至目前,您正在联系网络服务100次。您应该更改它,使其仅与一次联系网络服务,并检索所有100个图像的数组,而不是分别检索每个图像。
然后你可以遍历这个数组,这将非常快,因为不需要进一步的webtransactions。
答案 2 :(得分:2)
如果您从网络服务获取的图像本质上不是动态的,即不经常更改/修改,我建议在您的服务器上设置一个预定的进程/ cron作业,该作业从Web服务获取图像并在本地存储(在您的服务器本身中),因此您只能从服务器在网页上显示图像,并且每次向最终用户提供网页时都要避免第三方服务器往返。
答案 3 :(得分:1)
两个选项都无法解决您的问题,可能会让情况变得更糟。
对于选项1:
费用最多的时间是&#34; get_from_web_service($item)
&#34;,而代码只能由另一个脚本执行(如果文件&#34; get_image.php
& #34;在同一服务器上执行。)
对于选项2:
它只会使&#34; get-image-resource-request&#34;被浏览器触发,但您的服务器还需要处理&#34; get_from_web_service($item)
&#34;。
有一点必须明确的是,问题是关于get_from_web_service的性能,最直接的建议是让它具有更好的性能。另一方面,我们可以减少并发连接的数量。我没有想到这一点,只有2个建议:
异步:用户没有浏览整个页面,他们只会注意到顶部的页面。如果您提到的图像并未全部显示在顶部,您可以使用jquery.lazyload扩展,它可以使图像资源在不可见区域不会请求服务器,直到它们可见。
CSS Sprites :图像精灵是放入单个图像的图像集合。如果页面上的图像不会改变频率,您可以编写一些代码以便每天合并它们。
缓存图片:您可以将图像缓存在服务器或其他服务器上(更好)。并执行一些key-&gt;值工作:key是关于$ item,value是资源目录(url)。
我不是母语为英语的人,希望我能说清楚并对你有帮助。
答案 4 :(得分:0)
我不是专家,但我想每当你回声,它需要时间。得到100张图片不应该是一个问题(单独)
另外。也许get_from_web_service($item);
应该可以拿一个数组?
$counter = 1;
$urls = array();
foreach($items as $item)
{
$urls[$counter] = get_from_web_service($item);
$counter++;
}
// and then you can echo the information?
foreach($urls as $url)
{
//echo each or use a function to better do it
//echo '<img url="url_to_my_website/get_image?id='.$url->id.'" />'
}
get_image.php :
$url = get_from_web_service($item);
header("Content-Type: image/png");
echo file_get_contents($url);
最后,如果你能打电话
那将是非常好的get_from_web_service($itemArray); //intake the array and return images
答案 5 :(得分:0)
选项3: 将请求缓存到Web服务
答案 6 :(得分:0)
选项一是最佳选择。我还想确保图像缓存在服务器上,以便原始Web服务器不需要多次往返同一图像。
如果您感兴趣,这是我用于缓存图像等的代码的核心(注意,有一些东西,比如将相同的内容保留回客户端等):
<?php
function error404() {
header("HTTP/1.0 404 Not Found");
echo "Page not found.";
exit;
}
function hexString($md5, $hashLevels=3) {
$hexString = substr($md5, 0, $hashLevels );
$folder = "";
while (strlen($hexString) > 0) {
$folder = "$hexString/$folder";
$hexString = substr($hexString, 0, -1);
}
if (!file_exists('cache/' . $folder))
mkdir('cache/' . $folder, 0777, true);
return 'cache/' . $folder . $md5;
}
if (!isset($_GET['img']))
error404();
getFile($_GET['img']);
function getFile($url) {
// true to enable caching, false to delete cache if already cached
$cache = true;
$defaults = array(
CURLOPT_HEADER => FALSE,
CURLOPT_RETURNTRANSFER => 1,
CURLOPT_FOLLOWLOCATION => 1,
CURLOPT_MAXCONNECTS => 15,
CURLOPT_CONNECTTIMEOUT => 30,
CURLOPT_TIMEOUT => 360,
CURLOPT_USERAGENT => 'Image Download'
);
$ch = curl_init();
curl_setopt_array($ch, $defaults);
curl_setopt($ch, CURLOPT_URL, $_GET['img']);
$key = hexString(sha1($url));
if ($cache && file_exists($key)) {
return file_get_contents($key);
} elseif (!$cache && file_exists($key)) {
unlink($key);
}
$data = curl_exec($this->_ch);
$info = curl_getinfo($this->_ch);
if ($cache === true && $info['http_code'] == 200 && strlen($data) > 20)
file_put_contents($key, $data);
elseif ($info['http_code'] != 200)
error404();
return $data;
}
$content = getURL($_GET['img']);
if ($content !== null or $content !== false) {
// Success!
header("Content-Type: image");
echo $content;
}
答案 7 :(得分:0)
这两个选项都不会解决服务器资源使用问题。不过,我会建议选项1.第二个会延迟页面加载,导致网站速度变慢,并降低您的搜索引擎优化评级。
最适合您的选择是:
foreach($items as $item) {
echo '<img url="url_to_my_website/get_image.php?id='.$item->id.'" />'
}
然后神奇发生的地方是 get_image.php :
if(file_exists('/path_to_local_storage/image_'.$id.'.png')) {
$url = '/path_to_images_webfolder/image_'.$id.'.png';
$img = file_get_contents($url);
} else {
$url = get_from_web_service($id);
$img = file_get_contents($url);
$imgname = end(explode('/', $url));
file_put_contents($imgname, $img);
}
header("Content-Type: image/png");
echo $img;
这是每个图像只运行一次Web服务请求,然后将其存储在本地空间。下次请求图像时 - 您将从本地空间提供图像,跳过对Web服务的请求。
当然,将图像ID视为唯一且持久的。
可能不是最好的解决方案,但应该对你有用。
答案 8 :(得分:0)
正如我们在上面看到的那样,您在<img>
标记src
属性中包含了网络服务提供图片的网址,可以安全地假设这些网址不是机密或机密的。< / p>
知道上述情况,get_image.php
中的以下代码段将以最小的开销工作:
$url = get_from_web_service($id);
header("Location: $url");
如果您从给定的客户端收到大量后续请求id
,则可以通过利用浏览器的内部缓存来减少请求数量。
header("Cache-Control: private, max-age=$seconds");
header("Expires: ".gmdate('r', time()+$seconds));
通过Memcached,数据库或普通文件来实现服务器端缓存:
is_dir('cache') or mkdir('cache');
$cachedDataFile = "cache/$id";
$cacheExpiryDelay = 3600; // an hour
if (is_file($cachedDataFile) && filesize($cachedDataFile)
&& filemtime($cachedDataFile) + $cacheExpiryDelay > time()) {
$url = file_get_contents($cachedDataFile);
} else {
$url = get_from_web_service($id);
file_put_contents($cachedDataFile, $url, LOCK_EX);
}
header("Cache-Control: private, max-age=$cacheExpiryDelay");
header("Expires: ".gmdate('r', time() + $cacheExpiryDelay));
header("Location: $url");