php - 使用有效路径打开远程 pdf 文件返回 404

标签 php drupal http-status-code-404

我试图在 drupal 中显示与文章关联的相应 PDF 文件,这样如果浏览器配备了呈现 pdf 的功能,它应该直接打开,如果不显示带有“打开”、“保存”和“保存”的常规对话框“取消”允许用户在选项中进行选择。 PDF 存在于公共(public) Web 服务器中,可以访问所有资源(如图像和文件)。

我用来完成的代码如下:

$pdf_file_name = "http://mysite.com/valid-pdf-file.pdf";
drupal_set_header('Content-type: application/pdf');
drupal_set_header('Content-Disposition: inline; filename="' . $pdf_file_name
 . '"');
$fp = fopen($pdf_file_name, "r");
$file_open_timeout = 60;
if ($fp) {
  stream_set_timeout($fp, $file_open_timeout); 
  while (!feof($fp)) {
    echo fread($fp, 65536);
    flush();
  }
  fclose($fp);
}
else {
  watchdog("pdf logging", "Could not open the file " . $pdf_file_name);
}

虽然这段代码适用于我的一些初始 pdf 文件(我假设是最大 10 MB 的小文件),但它在许多其他文件上失败并显示以下错误消息:

fopen(http://mysite.com/valid-pdf-file.pdf): failed to open stream: HTTP request failed! HTTP/1.1 404 Not Found

打开该文件的路径 http://mysite.com/valid-pdf-file.pdf通过浏览器直接渲染文件,没有任何错误信息。因此,我基于一些谷歌搜索在上面的代码中尝试了 stream_set_timeout,但尽管文件确实存在,但仍然无法通过 404 错误。

这是一个无法打开的 URL 的示例:

"http://fileservername.com/resources/sitename/2013/03/20/bed6e3de-41bf-4bf9-bed8-d21508eaa8ca/Trouble --云纲要优化.pdf"

我也用 url 编码文件路径进行了测试,但结果没有什么不同;在 fopen 和 readfile 中做了 urlencode($pdf_file_name)

我进一步检查了这些麻烦的pdf文件的文件/文件夹权限是否与正常打开的文件/文件夹权限不同,但发现没有什么不同。

此文件处理的替代代码

ob_clean();
flush();
readfile($pdf_file_name);
exit();

给出了相同的结果,其中麻烦的 pdf 返回 404,而其他的工作正常。非常感谢任何关于我错过了什么来获得这个功能或更好地实现这个的建议。

最佳答案

您的问题确实是 URL 编码,但您不能只是 urlencode() 整个字符串,因为这也会转义一些需要保持原样的字符。我会建议这样的事情:

function escape_url($url)
{
    // Check that the input data is sane
    if (!$parts = parse_url($url)) {
        return false;
    }
    if (!isset($parts['scheme'], $parts['host'])) {
        return false;
    }

    // construct site base URL
    $result = $parts['scheme'] . '://';

    if (isset($parts['user'])) {
        $result .= $parts['user'];
        if (isset($parts['pass'])) {
            $result .= ':' . $parts['pass'];
        }
        $result .= '@';
    }

    $result .= $parts['host'];

    // Normalize path
    if (!isset($parts['path'])) {
        // if no path assume domain root
        $parts['path'] = '/';
    }
    $parts['path'] = preg_split('#/+#', $parts['path']); // split to path components
    $parts['path'] = array_map(function($part) { // ensure all components are correctly escaped
        return urlencode(urldecode($part));
    }, $parts['path']);
    $parts['path'] = implode('/', $parts['path']); // reconstruct string
    $result .= $parts['path'];

    // parse the query string an rebuild it
    if (isset($parts['query'])) {
        parse_str($parts['query'], $query);
        if (function_exists('get_magic_quotes_gpc') && get_magic_quotes_gpc()) {
            // undo magic_quotes
            array_walk_recursive($query, function(&$value) {
                $value = preg_replace('#\\\\([\'"\\\\\\x00])#', '$1', $value);
            });
        }
        $result .= '?' . http_build_query($query);
    }

    // add document fragment if present
    if (isset($parts['fragment'])) {
        $result .= '#' . $parts['fragment'];
    }

    return $result;
}

$url = 'http://fileservername.com/resources/sitename/2013/03/20/bed6e3de-41bf-4bf9-bed8-d21508eaa8ca/Trouble --Cloud Compendium optimized.pdf';
echo escape_url($url);
// output:
// http://fileservername.com/resources/sitename/2013/03/20/bed6e3de-41bf-4bf9-bed8-d21508eaa8ca/Trouble+--Cloud+Compendium+optimized.pdf

See it working

注意:这使用 parse_str()规范化 URL 上可能受 magic_quotes_gpc 影响的任何查询字符串配置选项。 此选项已弃用,不安全,应禁用,但您应该知道,如果启用它,它将影响此函数的输出。无法在运行时调整此设置,您需要确保在您的环境中禁用该设置。

编辑 更正了路径组件的潜在双重编码,添加了当 magic_quotes 搞砸时的修复。请注意,这些修复使用闭包,因此需要 PHP 5.3+,对于较低版本 create_function()或辅助函数可以被替换。

关于php - 使用有效路径打开远程 pdf 文件返回 404,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15759466/

相关文章:

drupal - 检查显示的帐户是否是用户帐户

php - 我如何为 Joomla 1.6 创建自定义错误页面 (404)?

php - 通过PHP运行 "onclick"

android - 如何在 Android 应用程序中使用 HTTP cookie?

drupal - 在 Scald dnd 中使用图像样式 (Drupal 7)

reactjs - React 返回 200 表示未找到页面?

ruby - youtube_it gem找不到视频时如何处理404响应

PHP 表单更新无需注销

php - 使用 PHP Curl 库的持久/保持事件 HTTP?

javascript - 使用 php 将 sql 转为 html