4

我有一个 php 脚本(实际上是https://drupal.org/project/file_force),它通过在响应中添加正确的标题来强制单击链接的用户下载该链接。

此链接 90% 的时间都可以正常工作。有时会传递不正确的内容长度,因此用户会得到明显截断的文件。该错误始终在特定文件上发生,但是如果重新上传了这些文件,则该错误可能不会出现在新实例上,这使我认为这不是文件的问题,而是某处的缓存。所以我每次都运行 clearstatcache() 无济于事。奇怪的是 php 传递了正确的文件大小,或者说是当我将它插入到日志文件的字符串传递时。

以下是相关代码:

  clearstatcache();
  return array(
    'Content-Type: ' . $mimeinfo,
    'Content-Disposition: ' . $disposition . '; filename="' . basename($filepath) . '";',
    // Content-Length is also a good header to send, as it allows the browser to
    // display a progress bar correctly.
    // There's a trick for determining the file size for files over 2 GB. Nobody
    // should be using this module with files that large, but… the sprintf()
    // trickery makes sure the value is correct for files larger than 2GB. See
    // note at http://php.net/filesize
    'Content-Length: ' . sprintf('%u', filesize($filepath)),
  );

sprintf('%u', filesize($filepath)) 在一个不工作的文件上的示例输出是在浏览器看到它时2682059以某种方式被转换为。1740048

我试过删除 sprintf 功能无济于事。我也尝试过完全不包含 Content-Length 声明,但无论如何都会有人附上不正确的值。最后一条证据可能表明其他一些代码正在覆盖我在此处设置的内容标头,但它似乎没有留下我在上述代码中更改的任何其他标头以测试该理论。

有什么想法在哪里看吗?

4

2 回答 2

2

我解决了这个问题。

结果发现 Drupal 中的另一个模块是添加自己的内容长度标头并从数据库而不是直接从文件中获取值(奇怪),并且它正在下游发生。通过颠倒模块获得标题的顺序,问题就消失了。我已经针对有问题的模块提交了错误报告。

于 2013-10-30T15:14:33.663 回答
1

资料来源:PHP 官方文档 - “header”函数

PHP中有一个名为 header 的函数,您想在实际页面加载之前使用它来设置标题:

这是函数的骨架:

void header ( string $string [, bool $replace = true [, int $http_response_code ]] )

解释:

参数:

  • 细绳

标头字符串。

有两个特殊情况的标头调用。第一个是以字符串“HTTP/”(大小写不重要)开头的标头,它将用于确定要发送的 HTTP 状态代码。例如,如果您已将 Apache 配置为使用 PHP 脚本来处理丢失文件的请求(使用 ErrorDocument 指令),您可能希望确保您的脚本生成正确的状态代码。

  • 代替

可选的 replace 参数指示该标头是否应该替换先前的类似标头,或者添加第二个相同类型的标头。默认情况下它将替换,但如果您将 FALSE 作为第二个参数传递,您可以强制多个相同类型的标头。

  • http_response_code

将 HTTP 响应代码强制为指定值。请注意,此参数仅在字符串不为空时才有效。

===

返回值:

不返回任何值。


例子:

<?php
    header('Location: http://www.example.com/'); //redirect to www.example.com
?>

注意:必须在发送任何输出之前调用该函数,即在任何 HTML 标记之前或在任何echo调用之前。

在你的情况下:

<?php
    header('Content-Length: ' . sprintf('%u', filesize($filepath)));
?>

默认情况下为 true 的 replace 参数将导致您的程序覆盖所有先前设置的“Content-Length”标头。

希望所有的解释都是值得的...... :)

于 2013-11-05T13:33:15.570 回答