无法强制 Web 服务器从磁盘重新加载图像
Posted
技术标签:
【中文标题】无法强制 Web 服务器从磁盘重新加载图像【英文标题】:Cannot force web server to reload image from disk 【发布时间】:2018-11-05 05:34:20 【问题描述】:背景
我的目标是构建一个显示页面幻灯片的 Web 服务器。有些幻灯片可能只是一张图片,而有些幻灯片可能是带有 css 的文本。
安全
没什么花哨的,不会暴露在外面的世界。
界面
用户必须能够修改文本幻灯片中的文本。
用户必须能够修改幻灯片上显示的图像。
图像必须以自动方式更改(网络上的另一台机器创建图像并且应该能够将该图像推送到服务器以进行显示。或者,服务器应该能够下载图像本身,无论哪种方式) .
我有什么
在这个领域知之甚少,我开始阅读和修补。 LAMP 服务器看起来很简单。
我复制了一个slideshow container from w3(我后来意识到,据知识渊博的人说这是一个糟糕的来源),并删除了我不需要的东西。
我创造了:
用户输入文本的表单,保存在纯文本文件中(嗯,在我更新 Ubuntu 之前它可以工作,我猜包升级破坏了一些东西,现在表单只显示原始 php 代码。编辑:需要重新启用mods,可能是因为 php 从 5 升级到 7:sudo a2enmod php7.2
)。
我自己的 html 文本幻灯片,从文件中读取。修改时从文件中读取它很麻烦。我认为txtFile.setRequestHeader('pragma', 'no-cache');
就是这样做的。
带有本地图像的幻灯片
我真正的真正问题
复制新图像代替用作图像幻灯片输入的文件不会更改服务器显示的图像。这似乎是一个普遍的问题,并且在一年中提出了几种解决方案。这些我都没有成功。文件末尾的随机字符串和地址(难以自动化?),这块在我的 index.html 头中:
+ <!-- attempt to reload images on change, does not work: -->
+ <meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" />
+ <meta http-equiv="Pragma" content="no-cache" />
+ <meta http-equiv="Expires" content="0" />
似乎浏览器,至少是 chrome,在避免缓存方面变得越来越严格。
所以在我的设置(Ubuntu 18.04、LAMP 的 apt 包和最近的 chrome)中,如何让我的服务器在显示幻灯片时从磁盘重新加载图像?
编辑:我不想刷新,服务器应该自动重新加载图像。
另一个可能实际上是罪魁祸首的模糊问题
我做事很奇怪吗?感觉开发这个比它应该做的更麻烦,所以我可能走错了路。你能引导我走向另一个更有意义的方向吗?
【问题讨论】:
我认为图像版本控制是您的最佳选择。每当您的用户上传新图像时,将该信息放入数据库中(如果有的话)并使用该行的 ID 使您的缓存爆裂。类似<img src="image.url?v=image.id">
我会尝试通过 php 文件提供图像:<img src="getImage.php?id=xy">
。根据我的经验(没有经过大量测试),它们不会被缓存。
在一个连续循环中使用 AJAX 来获取滑块的图像可能是一种有趣的方法。这样,即使没有刷新页面,它们也会持续更新。
【参考方案1】:
您可以通过更改 URL 来强制网络服务器从磁盘重新加载图像。由于您不想经常更改其名称或路径,因此您将为它提供一个 v 参数,例如:
<img src="/images/myimage.png?v=2">
如果你想重新加载它,然后将其更改为
<img src="/images/myimage.png?v=3">
等等。
【讨论】:
但我不想手动更改 html,甚至点击刷新。新版本的图片应单独显示在幻灯片中。 @Gauthier 这就是我建议你使用 Ajax 的原因。您可以在后端使用 PHP 来检索您想要的图像并让 JS 更新 DOM。无需手动更新任何来源或刷新页面。 @Gauthier 如果您想重新加载图像,您可以从服务器端放置您想要的任何版本。如果您想一直重新加载图像,请确保放在那里的东西总是不同的。如果你想在图片已经加载的时候改变它,只需使用 javascript 改变 v 的值。【参考方案2】:您正在尝试禁用浏览器缓存。虽然原则上缓存非常简单:浏览器保存加载的资源并在后续请求中从内存中提供它们,但跨浏览器/跨设备禁用它相当复杂。
您可以做的最简单的事情是为您的图像附加一个唯一的参数,以诱使浏览器相信它是不同的:
<img src="/path/to/image.jpg?v=<?php time(); ?>">
这将使您的浏览器始终加载<img>
,因为它会认为这是一个新文件。但是,禁用浏览器缓存,尤其是图像缓存会极大地影响性能。
更好的方法是为您的图像分配唯一标识符并将它们保存(在数据库中),因此它们的唯一参数仅在文件更改时才会更改。
这是一种无需数据库的方法,因为您只需要知道上次替换图像的时间:
在您的图片上传处理脚本中,上传成功后,还将当前时间戳写入服务器上的文件中(即:timestamp.txt
)。
在您的标记中,使用此文件的内容来标记您的图像:<img src="path/to/file.jpg?v=<?= file_get_contents('./timestamp.txt'); ?>">
每隔几秒进行一次读取timestamp.txt
的ajax 调用。当timestamp.txt
的内容与src
的v
参数不同时,将src
值替换为新的时间戳,导致浏览器立即重新加载文件。注意: ajax 本身将被缓存,除非您确保它不会被缓存:'timestamp.txt?v=' + new Date().getTime()
【讨论】:
但是,如何自动更新页面源以采用新的唯一标识符?我错过了一些东西。 @Gauthier:当您上传文件时,您会创建一个唯一标识符并将其保存在数据库中。当您提供图像时,您查询数据库以获取标识符。当您覆盖图像时,您会替换标识符。这样,未更改的图像将被缓存。改变的那些被重新加载。 @Gauthier - 还有一件事:您不需要将标识符附加到保存在服务器上的文件名中。名称可以保持原来的。如file.jpg
和file.jbg?v=bogus
都将加载file.jpg
。
好的,剩下的就是开始使用 db.看起来我不能只覆盖图像文件,有人必须告诉服务器它是一个新版本......
不是服务器不知道。是浏览器。现在您正在设计一种机制,让服务器能够告诉浏览器:“嘿,这个改变了。重新加载它!”以上是关于无法强制 Web 服务器从磁盘重新加载图像的主要内容,如果未能解决你的问题,请参考以下文章
如何在 cellEdit 之后强制从持久存储重新加载核心数据