You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何修改PHP代码实现网页导出PDF/Word格式报告?

问题描述

现有一套HTML/PHP表单系统,点击表单Line Z处的「Download」按钮会提交到fr_get.php执行。Line A处的下拉选择框包含「Hi」「Hello」「Good Morning」「Good Evening」四个选项,选中「Hi」并点击下载按钮时,会执行对应的hi.php文件。

现有表单代码:

<form method="get" action="fr_get.php">
    <h1>Report</h1>
    <select name="report"> <!-- Line A -->
        <?php
        foreach ($reports->getReports() as $report) {
            $users = $report->getAll('AllowedUser'); ?>

            <option value="<?= $report->path; ?>"><?= (is_array($users) && in_array('deleted',
                    $users) ? 'DELETED --- ' : '').$report->getFirst('Title'); ?></option>
            <?php
        }
        ?>
    </select>
    <div class="submit"><input type="submit" value="Download"/></div>   <!-- Line Z -->
</form>

fr_get.php现有代码:

<?php

$db = connect_mysql();

if (!is_admin()) {
    die('Access Denied.');
}

$report = $_GET['report'];

include($report);

需求:修改fr_get.php代码,实现点击下载按钮时,直接下载PDF或Word格式的报告文件。


修改方案

1. 优先处理安全校验(必须步骤)

原代码直接使用$_GET['report']包含文件,存在严重的路径遍历、代码注入风险,必须先对参数做严格校验:

<?php
$db = connect_mysql();

if (!is_admin()) {
    die('Access Denied.');
}

// 定义允许的报告文件白名单,拦截非法请求
$allowed_reports = [
    'hi.php',
    'hello.php',
    'good_morning.php',
    'good_evening.php'
];

$report = $_GET['report'] ?? '';

// 校验参数是否在白名单内
if (!in_array($report, $allowed_reports)) {
    die('Invalid report request.');
}

// 额外安全层:确保文件在当前目录下,避免跨目录访问
$report_path = __DIR__ . '/' . $report;
if (!file_exists($report_path) || !is_file($report_path)) {
    die('Report file not found.');
}

2. 添加下载响应逻辑

根据报告脚本的输出方式,分两种情况处理:

情况一:报告脚本直接输出文件二进制内容

如果hi.php等脚本直接生成PDF/Word的内容并输出,可在包含脚本前设置HTTP响应头,触发浏览器下载:

// 映射每个报告对应的文件名与MIME类型
$report_meta = [
    'hi.php' => ['filename' => 'hi_report.pdf', 'mime' => 'application/pdf'],
    'hello.php' => ['filename' => 'hello_report.docx', 'mime' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'],
    'good_morning.php' => ['filename' => 'morning_report.pdf', 'mime' => 'application/pdf'],
    'good_evening.php' => ['filename' => 'evening_report.docx', 'mime' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document']
];

$file_meta = $report_meta[$report];

// 设置下载响应头
header('Content-Type: ' . $file_meta['mime']);
header('Content-Disposition: attachment; filename="' . $file_meta['filename'] . '"');
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');

// 包含报告生成脚本,直接输出内容
include($report_path);
exit;

情况二:报告脚本生成物理文件

如果hi.php会生成一个临时物理文件(比如/tmp/hi_report.pdf),则读取文件内容并输出:

// 执行报告脚本,获取生成的文件路径
ob_start();
include($report_path);
$generated_file = ob_get_clean();

// 校验生成的文件是否存在
if (!file_exists($generated_file) || !is_file($generated_file)) {
    die('Generated report file not found.');
}

// 自动识别文件MIME类型
$finfo = new finfo(FILEINFO_MIME_TYPE);
$mime_type = $finfo->file($generated_file);

// 设置响应头
header('Content-Type: ' . $mime_type);
header('Content-Disposition: attachment; filename="' . basename($generated_file) . '"');
header('Content-Length: ' . filesize($generated_file));
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');

// 输出文件内容
readfile($generated_file);

// 若为临时文件,下载完成后删除
unlink($generated_file);
exit;

3. 补充说明

  • MIME类型需对应正确:PDF用application/pdf,新版Word(.docx)用application/vnd.openxmlformats-officedocument.wordprocessingml.document,旧版Word(.doc)用application/msword。
  • 若报告生成耗时较长,可添加缓冲处理避免输出乱码。

内容的提问来源于stack exchange,提问作者flash

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 13:05:29