2009-08-30 65 views
16

我想监视一些外部图像加载的频率。 所以我的想法是,而不是直接给一个URI是这样的:用PHP脚本服务图像vs直接加载图像

www.site.com/image1.jpg 

我可以创建一个PHP脚本读取图像,所以我建立了一个PHP文件和我的HTML看起来像这样:

<img src="www.site.com/serveImage.php?img=image1.jpg"> 

但我不知道如何从磁盘读取图像并将其返回。我会返回一个字节数组还是设置内容类型?

亲切的问候, 米歇尔

回答

9

您必须设置内容类型:

header("Content-type: image/jpeg"); 

然后加载这样的图像,并将其输出:

$image=imagecreatefromjpeg($_GET['img']); 
imagejpeg($image); 
+2

imagecreatefromjpeg + imagejpeg可能是有点矫枉过正(ANC CPU-consumming)如果你只是想从文件发送数据 - 优势我看到的是确保你真正加载图像;但可能有其他方法可以确定(如只允许一个目录,只包含图像) – 2009-08-30 13:30:54

+15

如果您只是要发送图像,readfile会更好。 – OIS 2009-08-30 19:08:09

20

为了实现这样的事情,您的脚本将需要:

  • 发出正确的头,这取决于图像的类型:image/GIF,图像/ PNG,图像/ JPEG,...
  • 发送图像
  • 的数据,确保没有别的是发送(没有空白,什么都没有)

这与header函数来完成,有些代码:

header("Content-type: image/gif"); 

header("Content-type: image/jpeg"); 

或其他什么,取决于图像的类型。


发送图像的数据,你可以使用readfile功能:

读取一个文件,并将其写入 输出缓冲区。

这样,在一个函数中,你既读取文件,又输出其内容。


一点题外话:

  • 你必须把一些安全的地方,确保用户无法要求他们通过你的脚本想要的东西:你必须确保它仅提供图像,从目录你期望的;例如,serveImage.php?file=/etc/passwd应该没问题。
  • 如果你只是愿意获得每天加载文件的次数,解析Apache的日志文件可能是一个好主意(通过cron每天在00:05运行批处理,解析日志文件例如前一天);你不会有实时统计数据,但它会需要更少的资源服务器上(没有PHP为静态文件)
+1

感谢您的支持:•您必须提供一些安全措施,以确保用户无法通过您的脚本请求任何他们想要的内容:您必须确保它只提供您期望的目录中的图像;没有像serveImage.php?file =/etc/passwd应该是可以的,例如。 – Michel 2010-01-08 15:57:12

3

你可能会更好过检查你的服务器访问日志本。通过php运行所有图像可能会给服务器带来一点负担。

+0

嗯,那肯定会诀窍。当负载成为问题时,我会保存它。 – Michel 2009-08-30 13:29:17

+0

另外,通过PHP脚本运行它们会影响客户端缓存,这实际上可能会增加读取负载。 – Rob 2009-08-30 18:55:20

+2

@rob:这与通过脚本运行它无关,但忘记发送正确的标题。我的答案中有两个最好的。 – OIS 2009-08-30 19:17:53

33

通过脚本发送图像很适合按需调整大小和缓存等其他内容。

如由Pascal MARTIN回答功能readfile和这些标头的要求是:

  • 内容类型
    • 的mime类型此内容的
    • 实施例:header('Content-Type: image/gif');
    • 见功能mime_content_type
    • 类型
      • image/gif
      • image/jpeg
      • image/png

但显而易见的内容类型,你也应该看看其他头,比如旁边:

  • 内容 - 长度
    • 响应主体的八位字节(8位字节)的长度
    • 实施例:header('Content-Length: 348');
    • 参见功能filesize
    • 允许connectio到得到更好的利用。
  • 上次修改
    • 用于所请求的对象的最后修改日期,在RFC 2822格式
    • 实施例:header('Last-Modified: Tue, 15 Nov 1994 12:45:26 GMT');
    • 参见功能filemtimedate将其格式化为所要求的RFC 2822格式
      • 实施例:header('Last-Modified: '.date(DATE_RFC2822, filemtime($filename)));
    • 如果文件修改时间相同,您可以在发送304后退出脚本。
  • 状态代码
    • 例子:header("HTTP/1.1 304 Not Modified");
    • 你,而不是现在可以退出发送图像一次

对于最后修改时间,在$_SERVER寻找这个

  • 的If-Modified-由于
    • 允许一个304未修改如果内容是不变
    • 实施例要被返回:If-Modified-Since: Sat, 29 Oct 1994 19:43:31 GMT
    • 是在$_SERVER与键http_if_modified_since

List of HTTP header responses

+0

这是一个很好的代码,有助于实现所有的头文件:[链接](http://css-tricks.com/snippets/php/intelligent-php-cache-control/) – 2014-08-04 13:39:18

2

另外,如果你想让用户看到一个真正的文件名ins你的脚本名的TEAD当用户RMC的图像上,并选择“另存为”,你还需要设置这个头:

header('Content-Disposition: filename=$filename'); 
+1

这也可以通过重定向来解决apache(虚拟主机或.htaccess)到脚本文件。所以/img/somefile_small.jpg将内部重定向到showimage.php – OIS 2010-09-03 21:44:38

11

我使用“中继”功能叫“猫”的命令,像这个:

header('Content-type: image/jpeg'); 
passthru('cat /path/to/image/file.jpg'); 

适用于Linux。节省资源。

6

除了在HTML中更改直接图像url,您可以在Apache配置或.htaccess中放置一行,以将目录中图像的所有请求重写为php脚本。然后在该脚本中,您可以使用请求标头和$_server数组来处理请求并提供文件。

首先在你的.htaccess:

RewriteRule ^(.*)\.jpg$ serve.php [NC] 
RewriteRule ^(.*)\.jpeg$ serve.php [NC] 
RewriteRule ^(.*)\.png$ serve.php [NC] 
RewriteRule ^(.*)\.gif$ serve.php [NC] 
RewriteRule ^(.*)\.bmp$ serve.php [NC] 

脚本serve.php必须在同一目录.htaccess。你可能会写这样的事情:(!该脚本可以提高)

<?php 
$filepath=$_SERVER['REQUEST_URI']; 
$filepath='.'.$filepath; 
if (file_exists($filepath)) 
{ 
touch($filepath,filemtime($filepath),time()); // this will just record the time of access in file inode. you can write your own code to do whatever 
$path_parts=pathinfo($filepath); 
switch(strtolower($path_parts['extension'])) 
{ 
case "gif": 
header("Content-type: image/gif"); 
break; 
case "jpg": 
case "jpeg": 
header("Content-type: image/jpeg"); 
break; 
case "png": 
header("Content-type: image/png"); 
break; 
case "bmp": 
header("Content-type: image/bmp"); 
break; 
} 
header("Accept-Ranges: bytes"); 
header('Content-Length: ' . filesize($filepath)); 
header("Last-Modified: Fri, 03 Mar 2004 06:32:31 GMT"); 
readfile($filepath); 

} 
else 
{ 
header("HTTP/1.0 404 Not Found"); 
header("Content-type: image/jpeg"); 
header('Content-Length: ' . filesize("404_files.jpg")); 
header("Accept-Ranges: bytes"); 
header("Last-Modified: Fri, 03 Mar 2004 06:32:31 GMT"); 
readfile("404_files.jpg"); 
} 
/* 
By Samer Mhana 
www.dorar-aliraq.net 
*/ 
?> 

0

我为我的图像与ReadFile的为好,但我已经加倍努力,无论是安全性和额外的功能。

我有一个数据库设置,其中存储的图像ID,其尺寸和文件扩展名。这也意味着需要上传图片(允许可选的调整大小),所以我只使用该系统的内容,而不是网站本身所需的图片(如背景或精灵)。

它也做了很好的工作,以确保您只能请求图像。

所以,对于服务于简化的工作流程是这样的(不能张贴在这里生产代码):

1)获得请求的图像

2的ID),看看它在数据库中

3)的基础上扩展( “JPG” 掷标头被重新映射到上载 “JPEG”)

4)readfile("/images/$id.$extension");

5)可选地,保护/ images/dir,使其无法被索引(在我自己的系统中不存在问题,因为它将URL映射为/image/view/11,类似于/index.php?module=image &操作=视图& ID = 11