7

我有一个网页x.php(在我网站的密码保护区域),它有一个表单和一个按钮,该按钮使用该POST方法发送表单数据并打开x.php#abc。这工作得很好。

但是,如果用户决定在 Internet Explorer 7 中导航回来,则原始字段中的所有字段都将x.php被清除,并且必须重新输入所有内容。我无法在会话中保存发布的信息,我试图了解如何让 IE7 以我想要的方式运行。

我在网上搜索并找到了建议 HTTP 标头应包含显式缓存信息的答案。目前,我已经尝试过:

session_name("FOO");
session_start();
header("Pragma: public");
header("Expires: Fri, 7 Nov 2008 23:00:00 GMT");
header("Cache-Control: public, max-age=3600, must-revalidate");
header("Last-Modified: Thu, 30 Oct 2008 17:00:00 GMT");

及其变体。没有成功。使用WireShark 之类的工具查看返回的标头表明 Apache 确实尊重我的标头。

所以我的问题是:我做错了什么?

4

6 回答 6

14

IE在单击后退按钮时自动保留表单内容,只要:

  • 您没有使用 no-cache pragma 或类似的方法破坏缓存
  • 有问题的表单字段不是由脚本动态创建的

您似乎手头有缓存,所以我猜后者可能适用。(正如 mkoeller 所说,如果页面在最后几次后点击中,Firefox 通过保持页面本身的活动时间比它在屏幕上的时间更长来避免这个问题。但是这是可选的,Firefox 将恢复到与 IE 和其他相同的行为浏览器之前浏览了几页并且旧页面已过期。)

如果您从脚本 onload 创建自己的表单字段,则浏览器无法知道新输入控件与旧实例“相同”,因此它无法使用先前提交的值填充它. 在这种情况下,如果您希望它与后退按钮一起玩得很好,您必须开始在客户端上存储数据。

然后您必须使用某种状态键控,以便每组数据都与页面的一个实例绑定,否则通过同一表单的多个实例或同时在表单上打开两个浏览器选项卡会严重混淆你的脚本。

然后如果它们是大型表单,您将开始收集大量数据,如果您使用的客户端存储机制是 cookie,您可能会开始丢失数据,并发送大量不必要的状态废话每个 HTTP 请求。其他客户端存储机制可用,但它们是特定于浏览器的。

简而言之:很好地完成动态生成的表单是一种巨大的痛苦,如果可以的话,最好避免这样做。在页面上有一个隐藏的表单,脚本使其可见,因此允许浏览器执行他们的字段记忆魔法而不是给你任务,通常要容易得多。

于 2008-11-04T11:16:26.677 回答
4

在尝试进一步缩小问题范围时,我找到了问题的原因。我使用的是由 Apache 重写的 URL(即,我总是访问http://foo.com/page由 Apache 映射到的我的页面http://foo.com/page.htm)。只要我指定正确的 HTTP 标头( , 等),使用真实的 URL 就可以解决问题并使IE7满意Cache-ControlExpires

这是我在 PHP 代码中所做的输出标头的操作,这似乎使所有浏览器都对缓存感到满意:

function emitConditionalGet($timestamp)
{
    // See also http://www.mnot.net/cache_docs/
    // and code sample http://simonwillison.net/2003/Apr/23/conditionalGet/

    $gmdate_exp    = gmdate('D, d M Y H:i:s', time() + 1) . ' GMT';
    $last_modified = gmdate('D, d M Y H:i:s', $timestamp) . ' GMT';
    $etag          = '"'.md5($last_modified).'"';

    // If the client provided any of the if-modified-since or if-none-match
    // infos, take them into account:

    $if_modified_since = isset($_SERVER['HTTP_IF_MODIFIED_SINCE'])
                       ? stripslashes($_SERVER['HTTP_IF_MODIFIED_SINCE']) : false;
    $if_none_match     = isset($_SERVER['HTTP_IF_NONE_MATCH'])
                       ? stripslashes($_SERVER['HTTP_IF_NONE_MATCH'])     : false;

    if (!$if_modified_since && !$if_none_match)
    {
        return;  // the client does not cache anything
    }

    if ($if_none_match && $if_none_match != $etag)
    {
        return;  // ETag mismatch: the page changed!
    }
    if ($if_modified_since && $if_modified_since != $last_modified)
    {
        return;  // if-modified-since mismatch: the page changed!
    }

    // Nothing changed since last time client visited this page.

    header("HTTP/1.0 304 Not Modified");
    header("Last-Modified: $last_modified");
    header("ETag: $etag");
    header("Cache-Control: private, max-age=1, must-revalidate");
    header("Expires: $gmdate_exp");
    header("Pragma: private, cache");
    header("Content-Type: text/html; charset=utf-8");
    exit;
}

function emitDefaultHeaders($timestamp)
{
    $gmdate_exp    = gmdate('D, d M Y H:i:s', time() + 1) . ' GMT';
    $last_modified = gmdate('D, d M Y H:i:s', $timestamp) . ' GMT';
    $etag          = '"'.md5($last_modified).'"';

    header("Last-Modified: $last_modified");
    header("ETag: $etag");
    header("Cache-Control: private, max-age=1, must-revalidate");
    header("Expires: $gmdate_exp");
    header("Pragma: private, cache");
    header("Content-Type: text/html; charset=utf-8");
}

function getTimestamp()
{
    // Find out when this page's contents last changed; in a static system,
    // this would be the file time of the backing HTML/PHP page. Add your
    // own logic here:
    return filemtime($SCRIPT_FILENAME);
}

// ...

$timestamp = getTimestamp();
emitConditionalGet($timestamp);
emitDefaultHeaders($timestamp); //previously, this variable was mistyped as "$timestaml"
于 2008-11-04T14:30:56.550 回答
3

Firefox 会进行这种缓存。据我了解您的问题,您希望 IE7 的行为方式与 Firefox 相同。我认为这是不可能的。

Firefox 和 IE7 在解释后退按钮的方式上有所不同。

Firefox 将显示上一页的 DOM 树,因为它在页面离开之前最后一次显示。也就是说,所有表单数据仍将包含在表单的输入字段中。onload但是您在点击后退按钮时不会看到事件。

IE7 将根据它从服务器接收到的响应再次呈现页面。因此表单是空的(除非服务器最初发送了默认值),但您会看到一个onload事件。

于 2008-11-04T10:06:28.737 回答
2

我四处寻找,这是一个相当困难的问题。这也是动态修改内容的一大痛点。您访问该页面,javascript 用您的指令对其进行扩充,您转到下一页,然后返回,javascript 已经忘记了。并且没有办法简单地更新页面服务器端,因为页面超出了缓存。

所以我设计了一个后退按钮缓存断路器。

它的邪恶和对网络不利,但它使页面能够按照人们期望的方式运行,而不是神奇地到处扭曲。

<script type="text/javascript">//<!-- <![CDATA[
(function(){
    if( document.location.hash === "" )
    {
        document.location.hash="_";
    }
    else
    {
      var l = document.location;
      var myurl = ( l.protocol + "//" + l.hostname + l.pathname + l.search); 
      document.location = myurl;
    }
})();
//]]> --></script>

这会产生一点魔力,因为它会检测您/当前/查看的页面是否是从缓存中加载的。

如果您是第一次来,它会检测到“无哈希”,并将“ #_”添加到页面 url。如果您第一次在那里(即:不是页面的直接链接),页面上已经有 #_,所以它会删除它并在删除它的过程中触发页面重新加载。

于 2008-11-04T10:45:18.673 回答
2

您可以在字段中使用 autocomplete="off"。这样,浏览器不会缓存这些值,因此当用户单击后退按钮时,这些值不会填充到表单中。

于 2008-11-04T12:12:08.373 回答
2

这是一个旧帖子,此后发生了很大变化。尽管如此,我的一种形式遇到了这个问题(但 Chrome 出现了问题。)如果返回它会清除所有信息。我完全巧合地找到了解决方法,需要在这里分享它,只是因为它太奇怪了。可能这不是发布此内容的最佳位置,但我们开始吧。

这就是我所拥有的(精简版并且无法正常工作。)

<table>
    <form>
    <tr>
        <td><input type="number" value="0"></td>
    </tr>
    </form>
</table>

这修复了它(现在可以工作了。)将标签移到标签<form>之外。<table><tr>

<form>
<table>
    <tr>
        <td><input type="number" value="0"></td>
    </tr>
</table>
</form>
于 2019-07-10T22:15:30.463 回答