图像数据在通往浏览器的途中被破坏

时间:2012-09-18 00:32:36

标签: php apache drupal drupal-7

我在LAMP环境下有一个在Drupal下运行的应用程序。它从数据库中提供图像。在我的个人计算机(OS X Lion)上,它运行正常。在开发服务器(Amazon EC2)上,完全相同的代码不起作用。两台服务器都运行PHP 5.3。我已经确认数据在echo $fileData和浏览器接收之间被破坏了。此外,我已经确认,如果数据是base64编码的,数据不会被破坏(我使用脚本来请求数据,解码数据并将其保存到文件中)。

在Drupal端,代码位于创建菜单回调的模块中;回调函数直接回显文件数据,以避免将整个图像存储在内存中(我正在使用PDO :: FETCH_BOUND与PDO :: PARAM_LOB创建一个流,但是当我试图找到问题时它正在进入一个字符串那不是吗)。菜单条目具有自定义传递回调,基本上什么都不做。我尝试刷新任何输出缓冲的想法,Drupal可能会为Unicode支持或其他东西努力,但这也无济于事。

我希望有人知道可能导致我的问题的原因。如果我还不够清楚,我会发布一些代码;现在它充满了注释掉的功能,因此需要进行一些清理。

更新1:

我把一些示例代码放在一起,但它没有显示错误;我可以将代码转换为Drupal模块来测试代码堆栈。但是,我已将错误范围缩小到echo $fileData。代码看起来像这样:

function example_menu() {
  $pages['mpicture/%'] = array(
    'title' => 'Picture handler',
    'page callback' => 'example_picture',
    'page arguments' => array(1),
    'delivery callback' => 'example_deliver_png',
    'access callback' => TRUE,
    'type' => MENU_CALLBACK,
  );
}

function example_picture($fileID) {
  // Point 1
  example_output_file($fileID);
}

function example_deliver_png($content) {
}

function example_output_file($fileID) {
  $statement = db_select('mfiles', 'f')
    ->fields('f', array('fileType', 'fileSize', 'fileData', 'fileData64', 'lastModified'))
    ->condition('fileID', $fileID, '=')
    ->execute();

  if ($file = $statement->fetchAssoc()) {
    header('Content-Type: ' . $file['fileType']);
    // Point 2
    header('Content-Length: ' . $file['fileSize']);
    echo $file['fileData'];
  }
}

这不起作用。如果我将Point 2更改为:

    // Point 2
    header('Content-Length: ' . $file['fileSize']*4/3);
    echo $file['fileData64'];

只要我的客户端在输出上运行base64_decode,它就能正常工作。但是,如果我这样做:

  // Point 1
  ob_start()
  example_output_file($fileID);
  $output = base64_encode(ob_get_clean());
  header('Content-Length: ' . strlen($output));
  echo $output;

...它不适用于同一个base64_decode客户端。怎么可能呢?

是的,我将数据存储两次;在我运行的每一个测试中,无论我使用$file['fileData']还是base64_decode($file['fileData64'])都没关系,所以我认为这不是数据库问题。

更新2:

但奇怪的是,这有效:

  // Point 1
  ob_start()
  example_output_file($fileID);
  $output = base64_encode(trim(ob_get_clean()));
  header('Content-Length: ' . strlen($output));
  echo $output;

所以,我想现在我试着找到打印空白区的位置?

1 个答案:

答案 0 :(得分:1)

我要掐死实习生。我发誓。不是真的,这是一种表达......但我很生气。

整个问题是因为他添加的新文件在其末尾有空格。一个简单的“?> \ n”。在服务器上的每个页面之前打印此空白区域,包括图像处理程序。白色空间使图像腐败。

我认为这里的道德观点是永远不要在文件末尾关闭PHP标签,并且确保与你合作的每个人都做同样的事情。