
本文旨在解决使用FPDF生成带密码保护的PDF文件时,通过前端AJAX请求无法正确触发下载,反而显示乱码的问题。这种现象通常发生在开发者尝试使用如jQuery的$.ajax方法异步请求服务器生成的二进制文件时,因为$.ajax默认将服务器响应视为文本处理,导致无法正确解析并触发浏览器对PDF等二进制文件的下载行为。核心方案是放弃传统的jQuery AJAX请求,转而采用XMLHttpRequest,并将其responseType设置为blob,从而正确处理服务器返回的二进制PDF数据,并在客户端触发文件下载,确保用户能够顺利获取受保护的PDF文件。
服务器端的PHP脚本负责使用FPDF_Protection库生成带有指定密码的PDF文件。关键在于设置PDF的保护选项,并利用Output('D', 'filename.pdf')指令,该指令会强制浏览器将响应作为文件下载。
<?php
// backend.php
// 确保只在接收到特定请求时执行PDF生成逻辑
if (isset($_POST["input"]) && $_POST["input"] == "generate_pdf") {
// 确保在输出任何内容之前开始缓冲,防止HTTP头发送前有意外输出
ob_start();
// 引入FPDF_protection库文件
require('FPDF_protection.php');
// 实例化FPDF_Protection对象
$pdf = new FPDF_Protection();
// 从POST数据获取用户密码,如果未提供则为空字符串
$userPassword = isset($_POST["password"]) ? $_POST["password"] : '';
// 设置PDF保护:例如,只允许打印,并指定用户密码
// 第一个参数是权限数组,例如array('print', 'copy', 'modify', 'annot-forms')
// 第二个参数是用户密码,第三个参数是所有者密码(可选)
$pdf->SetProtection(array('print'), $userPassword);
// 添加一个新页面
$pdf->AddPage();
// 设置字体
$pdf->SetFont('Arial', '', 12);
// 写入PDF内容
$pdf->Write(10, "Hello, this is a password protected PDF generated by FPDF_Protection.");
$pdf->Ln(); // 换行
$pdf->Write(10, "Please enter the password to view or print this document.");
// 输出PDF到浏览器,并强制下载
// 'D' 参数表示下载,"Recovery_code.pdf" 是下载时建议的文件名
$pdf->Output('D', "Recovery_code.pdf");
// 清除并关闭输出缓冲
ob_end_flush();
exit; // 确保脚本在此处终止,防止任何额外输出影响PDF文件完整性
}
?>注意事项:
为了正确处理服务器返回的二进制PDF数据并触发下载,我们需要使用XMLHttpRequest对象,并特别设置responseType为"blob"。Blob(Binary Large Object)接口代表了一个不可变的、原始数据的类文件对象,非常适合处理二进制数据。
立即学习“PHP免费学习笔记(深入)”;
以下是实现这一功能的JavaScript代码:
// 前端JS代码,例如绑定到一个按钮的点击事件
document.getElementById("downloadPdfButton").addEventListener("click", function() {
var password = document.getElementById("password").value;
var req = new XMLHttpRequest(); // 创建XMLHttpRequest对象
// 构造POST请求参数
var params = "input=generate_pdf&password=" + encodeURIComponent(password); // 编码密码以确保URL安全
// 配置请求:POST方法,目标URL,异步请求
req.open("POST", "backend.php", true);
// 关键:设置响应类型为blob,指示浏览器将响应数据视为二进制大对象
req.responseType = "blob";
// 设置请求头,告知服务器发送的数据类型是URL编码的表单数据
req.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
// 监听请求状态变化
req.onreadystatechange = function () {
// 当请求完成且成功(readyState为4,status为200)
if (req.readyState === 4 && req.status === 200) {
// 从响应中创建一个Blob对象,并指定MIME类型为application/pdf
var blob = new Blob([req.response], { type: 'application/pdf' });
// 创建一个临时的<a>标签用于触发下载
var link = document.createElement('a');
// 使用URL.createObjectURL创建指向Blob的URL
link.href = window.URL.createObjectURL(blob);
// 设置下载文件的名称
link.download = "Recovery_code.pdf";
// 将链接添加到DOM中(虽然不可见,但为了兼容性最好添加)
document.body.appendChild(link);
// 模拟点击链接,触发文件下载
link.click();
// 下载触发后,从DOM中移除链接
document.body.removeChild(link);
// 释放URL对象,避免内存泄漏,因为URL.createObjectURL创建的URL是临时的
window.URL.revokeObjectURL(link.href);
} else if (req.readyState === 4 && req.status !== 200) {
// 处理错误情况,例如服务器返回错误状态码
console.error("PDF下载失败,HTTP状态码:" + req.status);
// 如果服务器返回了错误信息,可以尝试读取:
// var reader = new FileReader();
// reader.onload = function() {
// console.error("错误详情:" + reader.result);
// };
// reader.readAsText(req.response); // 注意:如果responseType是blob,这里可能需要特殊处理
}
};
// 发送请求
req.send(params);
});请注意,上述代码中的document.getElementById("downloadPdfButton")和document.getElementById("password")是示例元素ID,您需要根据实际HTML结构进行调整。
当需要通过AJAX下载由PHP FPDF等服务器端库生成的二进制文件(如PDF)时,传统的jQuery $.ajax方法由于其默认的文本处理机制,往往无法满足需求。通过采用XMLHttpRequest并将其responseType设置为"blob",结合URL.createObjectURL()和HTML5的download属性,我们可以构建一个健壮且高效的客户端下载机制。这种方法能够确保二进制数据被正确处理,并触发浏览器下载,从而为用户提供无缝的文件获取体验。同时,务必注意URL.revokeObjectURL()的调用,以优化内存使用,确保应用程序的长期稳定运行。
以上就是使用XMLHttpRequest实现PHP FPDF生成的密码保护PDF文件下载的详细内容,更多请关注php中文网其它相关文章!
PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号