使用PDFAnnotate和jsPDF生成PDF后如何上传保存到PHP服务端
问题排查与修复方案
核心问题定位
前端问题
- 原生XHR提交时,
xhr.send()传入的是字符串'pdf',而非你构造好的formData对象,根本没有提交PDF文件数据 - 如果改用jQuery ajax提交FormData,需要额外设置两个参数避免jQuery自动处理数据导致上传失败
后端问题
- 即使前端正确提交了文件,后端逻辑也错误:文件数据存储在
$_FILES全局变量中,你判断了$_FILES['pdf']存在,却从$_POST里取数据,必然取不到有效内容 - 没有验证存储目录的存在性和写入权限,即使拿到文件也可能写入失败
排查步骤
- 打开浏览器开发者工具的「网络」面板,触发上传后查看对应POST请求:
- 检查请求头
Content-Type是否为multipart/form-data且带有boundary参数 - 检查请求载荷中是否包含PDF的二进制数据
- 查看接口返回的错误信息,确认是触发了
no data异常还是其他报错
- 检查请求头
- 服务端临时添加调试代码,输出
var_dump($_FILES, $_POST),查看实际接收到的数据结构 - 检查服务端
testa/pdf目录是否存在,对应进程是否有该目录的写入权限
修复代码
前端(原生XHR版本)
PDFAnnotate.prototype.savePdf = function() { var inst = this; var doc = new jspdf.jsPDF(); inst.fabricObjects.forEach(function(fabricObj, index) { if (index != 0) { doc.addPage(); doc.setPage(index + 1); } doc.addImage( fabricObj.toDataURL({ format: 'png' }), inst.pageImageCompression == "NONE" ? "PNG" : "JPEG", 0, 0, doc.internal.pageSize.getWidth(), doc.internal.pageSize.getHeight(), `page-${index + 1}`, ["FAST", "MEDIUM", "SLOW"].indexOf(inst.pageImageCompression) >= 0 ? inst.pageImageCompression : undefined ); if (index === inst.fabricObjects.length - 1) { var blob = doc.output('blob'); var formData = new FormData(); formData.append('pdf', blob, 'generated.pdf'); // 第三个参数可选,指定文件名 var xhr = new XMLHttpRequest(); xhr.open('POST', baseurl + "wo/replaceFile", true); // 不要手动设置Content-Type,浏览器会自动生成带boundary的正确值 xhr.send(formData); // 这里传构造好的formData,不是字符串'pdf' } }) }
前端(jQuery Ajax版本,符合前期调研选型)
// 替换上述代码中XHR部分即可 $.ajax({ url: baseurl + "wo/replaceFile", type: 'POST', data: formData, processData: false, // 禁止jQuery自动序列化FormData contentType: false, // 禁止jQuery自动设置Content-Type success: function(res) { console.log('上传成功', res) }, error: function(err) { console.log('上传失败', err) } })
后端修复代码
if(!empty($_FILES['pdf'])) { // 从$_FILES取临时文件路径 $tmpPath = $_FILES['pdf']['tmp_name']; $fname = "test.pdf"; $saveDir = "testa/pdf/"; // 先判断目录不存在就创建 if (!is_dir($saveDir)) { mkdir($saveDir, 0755, true); } $savePath = $saveDir . $fname; // 用move_uploaded_file移动临时文件更安全,比fwrite可靠 if (move_uploaded_file($tmpPath, $savePath)) { echo json_encode(['code' => 0, 'msg' => '保存成功']); } else { throw new Exception("文件保存失败,请检查目录权限"); } } else { throw new Exception("no data"); } ?>
内容的提问来源于stack exchange,提问作者siayam rumput
相关产品推荐
相关产品推荐

