如何通过AJAX将LocalStorage中的JS对象传入PHP并生成Excel?
问题:AJAX传输问卷数据到PHP后,无法整合PhpSpreadsheet生成Excel
当前实现情况
- 已将用户问卷输入保存至LocalStorage的JavaScript对象,通过AJAX POST请求传输到PHP文件
- AJAX请求成功,控制台能看到PHP返回的完整数据数组,但直接在浏览器打开PHP文件会显示空数组(正常,因为无POST请求)
- 单独的数组遍历代码可正常运行,但加入PhpSpreadsheet代码后出错,无法整合生成可下载的Excel文件
现有代码片段
AJAX请求代码
$.ajax({ url: '../wp-content/themes/elsa_theme/page-survey-to-ajax.php', type: "POST", dataType: "text", data: parsedSurvey, success: function(data) { console.log(data); // 控制台成功输出对象 } });
原PHP接收代码(page-survey-to-ajax.php)
<?php if (isset($_POST)) { $json = json_encode($_POST); $jsonD = json_decode($json, true); print_r($jsonD); } else { echo 'nothing to show'; } ?>
控制台返回的数组数据(部分)
Array ( [transport] => Array ( [bensin] => Array ( [name] => bensin [index] => 1 [excelSheet] => Transport [keyword] => Bensin [totEmissions] => 220 [parameters] => Array ( [0] => Array ( [excelCell] => G8 [coefficient] => 0.32 [percent] => false [value] => 200 [emissions] => 64 ) ) ) ) [lokaler] => Array ( [studio] => Array ( [name] => studio [index] => 11 [excelSheet] => Lokaler och boende [keyword] => studio [totEmissions] => 1000 [parameters] => Array ( [0] => Array ( [excelCell] => F8 [coefficient] => 5 [percent] => false [value] => 200 [emissions] => 1000 ) ) ) ) )
PhpSpreadsheet加载模板代码
require 'vendor/autoload.php'; use PhpOffice\PhpSpreadsheet\Spreadsheet; use PhpOffice\PhpSpreadsheet\Writer\Xlsx; use PhpOffice\PhpSpreadsheet\IOFactory; $template = get_stylesheet_directory_uri() . '/assets/php/elsa_report.xlsx'; $file = file_get_contents($template); $inputFileName = 'tempfile.xlsx'; file_put_contents($inputFileName, $file); $spreadsheet = \PhpOffice\PhpSpreadsheet\IOFactory::load($inputFileName);
数据遍历代码(单独运行正常)
foreach($jsonD as $cats){ foreach($cats as $question){ $sheet = $question['excelSheet']; $tot = $question['totEmissions']; $parameters = $question['parameters']; if (intval($tot) != 0) { foreach($parameters as $parameter){ $cell = $parameter['excelCell']; $value = $parameter['value']; // $spreadsheet->getSheetByName($sheet)->getCell($cell)->setValue($value); } } } }
完整解决方案
1. 修正PHP文件逻辑(整合数据接收与Excel生成)
替换page-survey-to-ajax.php的全部代码,解决路径错误、请求验证和下载响应问题:
<?php // 仅允许POST请求访问 if($_SERVER['REQUEST_METHOD'] !== 'POST'){ echo '仅支持POST请求'; exit; } // 接收POST数据 $surveyData = $_POST; if(empty($surveyData)){ echo '无有效数据'; exit; } // 加载PhpSpreadsheet依赖 require 'vendor/autoload.php'; use PhpOffice\PhpSpreadsheet\IOFactory; use PhpOffice\PhpSpreadsheet\Writer\Xlsx; // 注意:使用本地文件路径而非URL $templatePath = get_stylesheet_directory() . '/assets/php/elsa_report.xlsx'; if(!file_exists($templatePath)){ echo '模板文件不存在'; exit; } // 加载Excel模板 $spreadsheet = IOFactory::load($templatePath); // 遍历数据写入对应单元格 foreach($surveyData as $category){ foreach($category as $item){ $sheetName = $item['excelSheet']; $totEmissions = intval($item['totEmissions']); // 仅处理有排放数据的项 if($totEmissions !== 0){ // 获取目标工作表,不存在则跳过 $sheet = $spreadsheet->getSheetByName($sheetName); if(!$sheet) continue; foreach($item['parameters'] as $param){ $cell = $param['excelCell']; $value = $param['value']; // 写入单元格值 $sheet->getCell($cell)->setValue($value); } } } } // 设置浏览器下载响应头 header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'); header('Content-Disposition: attachment;filename="survey_report.xlsx"'); header('Cache-Control: max-age=0'); // 输出Excel文件 $writer = new Xlsx($spreadsheet); $writer->save('php://output'); exit; ?>
2. 调整前端逻辑(解决AJAX无法下载文件问题)
AJAX无法直接处理文件下载响应,改用表单提交到新窗口的方式:
// 创建隐藏表单 let downloadForm = document.createElement('form'); downloadForm.method = 'POST'; downloadForm.action = '../wp-content/themes/elsa_theme/page-survey-to-ajax.php'; downloadForm.target = '_blank'; // 将parsedSurvey对象转为表单字段 function appendFormFields(obj, parentKey = '') { for(let key in obj) { if(typeof obj[key] === 'object') { appendFormFields(obj[key], parentKey ? `${parentKey}[${key}]` : key); } else { let input = document.createElement('input'); input.type = 'hidden'; input.name = parentKey ? `${parentKey}[${key}]` : key; input.value = obj[key]; downloadForm.appendChild(input); } } } appendFormFields(parsedSurvey); // 提交表单并移除 document.body.appendChild(downloadForm); downloadForm.submit(); setTimeout(() => document.body.removeChild(downloadForm), 500);
关键注意事项
get_stylesheet_directory_uri()返回的是URL,不能用于本地文件操作,必须用get_stylesheet_directory()获取服务器本地路径- 确保PhpSpreadsheet已通过Composer正确安装(执行
composer require phpoffice/phpspreadsheet) - 处理工作表时加入存在性判断,避免因模板缺失工作表导致报错
内容的提问来源于stack exchange,提问作者ilariaroglieri
相关产品推荐
相关产品推荐

