使用PHP脚本提供图像与直接加载图像

时间:2009-08-30 13:19:45

标签: php

我想监控一些外部图像的加载频率。 所以我的想法不是像这样直接给出一个uri:

www.site.com/image1.jpg

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

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

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

亲切的问候, 米歇尔

8 个答案:

答案 0 :(得分:34)

通过脚本发送图像非常适合其他事情,例如根据需要调整大小和缓存。

正如Pascal MARTIN所回答,函数readfile和这些标题是要求:

  • 内容类型
    • 此内容的mime类型
    • 示例:header('Content-Type: image/gif');
    • 查看函数mime_content_type
    • 类型
      • image/gif
      • image/jpeg
      • image/png

但除了显而易见的内容类型之外,您还应该查看其他标题,例如:

  • 的Content-Length
    • 以八位字节为单位的响应正文的长度(8位字节)
    • 示例:header('Content-Length: 348');
    • 查看函数filesize
    • 允许更好地使用连接。
  • 上次修改
    • 请求对象的上次修改日期,采用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

中查找
  • 如果-Modified-Since的
    • 如果内容未更改,则允许返回304 Not Modified
    • 示例:If-Modified-Since: Sat, 29 Oct 1994 19:43:31 GMT
    • 使用密钥$_SERVER
    • http_if_modified_since

List of HTTP header responses

答案 1 :(得分:20)

要实现这样的目标,您的脚本需要:

  • 发送正确的标题,这取决于图像的类型:image / gif,image / png,image / jpeg,...
  • 发送图像数据
  • 确保没有发送(没有空格,没有任何内容)

这是通过header函数完成的,其代码如下:

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

或者

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

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


要发送图像数据,您可以使用readfile功能:

  

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

这样,在一个函数中,您既可以读取文件,也可以输出其内容。


作为旁注:

  • 您必须设置一些安全措施,以确保用户无法通过您的脚本请求他们想要的任何内容:您必须确保它只从您期望的目录中提供图像;例如,serveImage.php?file=/etc/passwd之类的内容应该没问题。
  • 如果您只是愿意获取每天加载文件的次数,解析Apache的日志文件可能是一个好主意(通过cron每天00:05批量运行,解析日志前一天,例如);您将无法获得实时统计信息,但它将需要更少的资源(没有PHP来提供静态文件)

答案 2 :(得分:12)

我使用“passthru”函数调用“cat”命令,如下所示:

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

适用于Linux。节省资源。

答案 3 :(得分:9)

您必须设置内容类型:

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

然后加载图像并输出如下:

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

答案 4 :(得分:6)

您可以在Apache配置或.htaccess中添加一行来将目录中图像的所有请求重写为php脚本,而不是更改HTML中的直接图像URL。然后在该脚本中,您可以使用请求标头和$_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
*/
?>

(这个脚本可以改进!)

答案 5 :(得分:3)

为此,您可能最好检查服务器访问日志。通过php运行所有图像可能会给您的服务器带来一些负担。

答案 6 :(得分:2)

此外,如果您希望用户在图像上的用户RMC上查看真实文件名而不是您的脚本名称并选择“另存为”,则还需要设置此标题:

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

答案 7 :(得分:0)

我也使用readfile提供图像,但为了安全性和额外的功能,我已经付出了额外的努力。

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

它还确保您只能请求图像。

因此,为了提供简化的工作流程就像这样(不能在这里发布生产代码):

1)获取所请求图像的ID

2)在数据库中查找

3)根据扩展名投掷标题(&#34; jpg&#34;重新映射到&#34; jpeg&#34;上传时)

4)protected void tryLetter(View v){

5)(可选)保护/ images / dir,使其无法编入索引(在我自己的系统中不是问题,因为它将 / image / view / 11 等URL映射到 / ?的index.php模块=图像&安培;行动=视图和ID = 11