file_get_contents或readfile用于显示文件系统映像

rob*_*lls 12 php function

任何人都可以建议什么是最好的PHP函数来显示存储在文件系统中的图像 - file_get_contents或者readfile.我们正在显示存储在数据库中的图像,因此我们仍然需要通过PHP文件调用图像,并且无法直接链接到文件系统.我见过人们推荐这两种功能,但我倾向于使用readfile.将不胜感激.

Ste*_*rig 26

如果您不需要操作图像(调整大小,添加水印,......)readfile()将是最佳选择,因为它将文件直接写入输出缓冲区.file_get_contents()将文件读入内存 - 需要大量内存和大文件.


rix*_*rrr 9

编写这样的脚本时一定要考虑缓存!

当在下一页访问时重新请求图像时,服务静态图像的网络服务器将与客户端进行协商,并且如果服务器确定客户端的图像的缓存副本仍然有效,则图像将不是重发.

由于天真脚本不进行此协商,因此在每次页面请求时都会将图像重新传输到客户端,从而导致您的带宽超出必要的带宽.

这有三种机制.我无法确切地告诉你如何编写最佳脚本,因为我以前从未必须这样做,我不确定不同的缓存头如何互操作以及HTTP版本,但我鼓励你研究这个进一步.

我所知道的三种机制:

过期(HTTP/1.0)

最简单的一个.此标题告诉客户端图像在给定的时刻之前肯定会有效.在此时间过去之前,客户端甚至不会对脚本执行请求,因此适当地设置此选项可以节省您(部分)服务器上的CPU周期以及Web应用程序中的图像加载延迟.

你应该如何设置这完全取决于你的应用程序; 你的图像变化很快或很少?如果图像在您发送到客户端的Expires时间之前发生更改,则客户端将看不到新图像.

例:

header("Expires: " . gmdate('D, d-M-Y H:i:s \G\M\T', time() + 60)); // Valid for a minute
Run Code Online (Sandbox Code Playgroud)

(注意:Expires似乎已被HTTP/1.1中的Cache-Control取代)

If-Modified-Since(HTTP/1.1)

如果HTTP/1.1客户端已经拥有该映像的副本,则它可以发送此标头,并记录该副本的发布时间.然后,您可以在数据库中确定当前版本的映像是在更早或更晚的时间更改的.如果客户端的版本仍然是正确的,只需发送"304 Not Modified"响应并退出(从而防止必须传输图像).

例:

$cache_time   = parse_browsers_date_time_format($_SERVER["IF-MODIFIED-SINCE"]);
$actual_time  = get_current_resource_time_from_db();

if ($actual_time <= $cache_time) {
    header("HTTP/1.1 304 Not Modified");
    die;
}

// ... Produce and output resource here
Run Code Online (Sandbox Code Playgroud)

(注意:如果您还在原始响应中发送Last-Modified,客户端实际上可能只发送If-Modified-Since.我不确定,为自己研究.)

ETag/If-None-Match(HTTP/1.1)

此方法类似于If-Modified-Since协商,但它使用图像的哈希值来查看内容是否已更改.它的工作原理如下:服务器为图像计算一些哈希值,并在第一次在ETag头中请求图像时发送此哈希值.

在后续请求中,服务器将在请求字段If-None-Match中发回回哈希.如果客户端的哈希值与图像的当前哈希值相同,则图像之间没有更改,脚本只需发送"304 Not Modified"即可.

由于ETags似乎实际上是用来防止带有副作用的客户端请求中的并发问题(即POST和PUT),并且因为计算哈希是一项代价高昂的操作,我认为If-Modified-Since方法将是一个更适合大多数文件服务应用程序.