1

Drupal 开发人员,

我有一个非常奇怪的问题。我有一个带有菜单项的小模块,它输出图像 - 换句话说,它不显示任何页面、任何 HTML 或其他任何内容,而只是发送 aheader('Content-Type: image/png');然后输出 PNG 并退出exit();

但是......这真的很奇怪......有时即使我只加载一次URL,它也会运行两次并通过函数两次。如果我在函数中添加一个看门狗并检查日志后记,我可以看到该函数已经被处理了两次......有时。没有明显的原因,它偶尔会按预期工作 - 一次通过,一张图像输出,然后什么也没有,但在其他时候它会运行两次。

如果我在数据库中添加一个增加一个数字的计数器,这个数字有时会增加 1,有时会增加 2,尽管我只在浏览器中加载了一次图像。

我已经在两台服务器(一台 Unix,一台 Windows)上对其进行了测试......同样的不稳定行为。

我一直关注标头和缓存,但看不出有什么问题。当我输出 1x1 PNG 时,图像的标题如下所示:

Date: Thu, 04 Oct 2012 09:21:51 GMT
Server: Apache/2.2.22 (Win32) PHP/5.2.17
X-Powered-By: PHP/5.2.17
Expires: Sun, 19 Nov 1978 05:00:00 GMT
Last-Modified: Thu, 04 Oct 2012 09:21:51 +0000
Cache-Control: no-cache, must-revalidate, post-check=0, pre-check=0
Etag: "1349342511"
Content-Length: 95
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Content-Type: image/png

200 OK

如果我在这里和那里添加看门狗,我可以看到模块初始化不止一次,这并不奇怪,但我的自定义函数被多次调用真的让我感到惊讶——而且只是有时。我尝试了各种魔术,比如添加一个会话变量来计算第一次之后的通过和中断次数,但无济于事。该函数运行不止一次......大部分时间。

对于函数的目的来说,它总是运行一次且只运行一次是至关重要的。

有人知道发生了什么吗?

这是我的基本代码:

function my_image_menu() {
  $items = array();
  $items['image_1x1'] = array(
    'title' => t('Create image'),
    'description' => t('Output 1x1 PNG.'),
    'page callback' => 'my_image_show',
    'access arguments' => array('access content'),
  );

  return $items;
}

function my_image_show() {
  watchdog('My Image', 'Image shown');
  if (!headers_sent()) {
    header('Content-Type: image/png');
    echo base64_decode('iVBORw0KGgoAAAANSUhEUgAAAAEAAAABAQMAAAAl21bKAAAAA1BMVEUAAACnej3aAAAAAXRSTlMAQObYZgAAAApJREFUCNdjYAAAAAIAAeIhvDMAAAAASUVORK5CYII=');
    exit();
  }
}

如果我加载http://mysite/image_1x1,我会按预期在屏幕上看到一个漂亮的 1x1 小点,但大多数时候(但不是每次......)我会在日志中看到两个“显示的图像”条目!尽管 ,exit()据我所知应该停止脚本。

Drupal 可能会对我做什么巫术?

4

3 回答 3

0

我通过不在代码中输出图像而是通过标题命令将浏览器发送到物理图像文件来部分解决了这个问题。

这似乎破坏了 Drupal 中的任何流程并按预期渲染图像一次。唯一的缺点是我不能只生成任何图像,而是必须在物理上拥有它,但这是我可以克服的障碍。

换句话说,替换

  if (!headers_sent()) {
    header('Content-Type: image/png');
    echo base64_decode('iVBORw0KGgoAAAANSUhEUgAAAAEAAAABAQMAAAAl21bKAAAAA1BMVEUAAACnej3aAAAAAXRSTlMAQObYZgAAAApJREFUCNdjYAAAAAIAAeIhvDMAAAAASUVORK5CYII=');
    exit();   }

  if (!headers_sent()) {
    header('location:/sites/default/files/1px.png');
  }

在我的问题中的代码中,并确保 /sites/default/files/1px.png 在服务器上。

这现在对我有用,但我仍然很高兴知道什么可以阻止我猜是 Drupal 对exit()ordie()命令的处理。

马丁

于 2012-10-11T08:04:47.740 回答
0

也许这个,也许不是!--- watchdog() 和 exit() 都向日志报告。您的 watchdog() 不是有条件的 - 所以它总是会记录。您的 exit() 处于条件状态,因此仅在满足条件时才会记录。这可以解释巫毒教。

尝试 die() 而不是 exit() 以获得更清晰的日志。

于 2012-10-08T09:50:37.903 回答
-1

也许你应该尝试在“干净”的浏览器上检查这个。试试不带任何扩展的 Firefox(不是 Chrome!)。添加

watchdog('My Image debug info', print_r($_SERVER, true));

并分析此输出。

于 2012-10-08T12:55:15.330 回答