当前位置: 首页 > news >正文

Thinkphp使用pptx模板生成pptx

<?php
use DOMDocument;
use RecursiveDirectoryIterator;
use RecursiveIteratorIterator;
use ZipArchive;class PptxXmlModifier
{private $tempDir;private $namespaceA = 'http://schemas.openxmlformats.org/drawingml/2006/main';// 1. 解压 PPTX 文件private function unzip($pptxPath){//$this->tempDir在$zip->addFile($filePath, $relativePath);使用中;relativePath 必须是 Zip 内部相对路径,使用 正斜杠 /,否则会导致 PPTX 无法打开。$uniqid_file_path = ROOT_PATH .  'runtime/cache/uniqid/'.'pptx_' . uniqid();$this->tempDir = str_replace('\\', '/',$uniqid_file_path);if (!is_dir($this->tempDir)) {mkdir($this->tempDir, 0777, true); // 递归创建目录
        }$zip = new ZipArchive();if ($zip->open($pptxPath) === TRUE) {$zip->extractTo($this->tempDir);$zip->close();return true;}return false;}// 2. 替换文本(保留 Run 样式结构)private function replaceText($replacements){$slidesPath = $this->tempDir . '/ppt/slides';$slideFiles = glob($slidesPath . '/slide*.xml');foreach ($slideFiles as $slideFile) {$dom = new DOMDocument();$dom->preserveWhiteSpace = false;$dom->formatOutput = true;$dom->load($slideFile);// 获取所有 <a:t> 文本节点$textNodes = $dom->getElementsByTagNameNS($this->namespaceA, 't');foreach ($textNodes as $node) {$originalText = $node->nodeValue;foreach ($replacements as $placeholder => $newValue) {if (strpos($originalText, $placeholder) !== false) {// 核心:只修改节点的值,完全不触碰父级 <a:r> 和 <a:rPr> 中的任何样式属性$node->nodeValue = str_replace($placeholder, $newValue, $originalText);}}}$dom->save($slideFile);}}// 3. 替换图片(支持本地路径和 Base64 字符串)private function replaceImage($imageMap){// $imageMap 格式: ['old_image_filename.jpg' => '新的图片数据']$mediaDir = $this->tempDir . '/ppt/media';foreach ($imageMap as $oldName => $newImagepath) {$newImageSource = ROOT_PATH . $newImagepath;// PPT中的目标图片$targetImage = $mediaDir . '/' . $oldName;if (file_exists($targetImage)) {$data = file_get_contents($newImageSource);if ($data) {// 替换图片
                    file_put_contents($targetImage, $data);}}}}// 4. 重新打包成新的 PPTXprivate function save($outputPath){$zip = new ZipArchive();if ($zip->open($outputPath, ZipArchive::CREATE | ZipArchive::OVERWRITE) !== TRUE) {return false;}$files = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($this->tempDir),RecursiveIteratorIterator::LEAVES_ONLY);foreach ($files as $file) {if (!$file->isDir()) {$filePath = $file->getRealPath();$relativePath = substr($filePath, strlen($this->tempDir) + 1);$zip->addFile($filePath, $relativePath);}}return $zip->close();}// 清理临时文件private function cleanup(){if (is_dir($this->tempDir)) {$this->rrmdir($this->tempDir);}}private function rrmdir($dir){if (is_dir($dir)) {$objects = scandir($dir);foreach ($objects as $object) {if ($object != "." && $object != "..") {if (is_dir($dir . "/" . $object)) $this->rrmdir($dir . "/" . $object);else unlink($dir . "/" . $object);}}rmdir($dir);}}/*** @param $template  模板* @param $outputPath 输出文件全路径* @param $textReplacements  文本更换内容* @param $imageReplacements  图片更换内容* @return bool*/public function createpptx($template, $outputPath, $textReplacements, $imageReplacements){if ($this->unzip($template)) {// 3. 执行替换$this->replaceText($textReplacements);$this->replaceImage($imageReplacements);// 4. 保存并输出新文件$this->save($outputPath);$this->cleanup();return true;} else {return false;}}
}

使用

 $template = ROOT_PATH . P_STATIC . DS . 'template.pptx';$file_path = ROOT_PATH . P_STATIC . DS . 'week' . DS . $day;if (!is_dir($file_path)) {mkdir($file_path, 0777, true); // 递归创建目录
            }$output = $file_path . DS . $shopid . '.pptx';$textReplacements = ['{{username}}' => $user_data['name'],'{{shopname}}' => $shop_data['shop_name']];$feilds = ['1'=>['image3.png','image4.png','image5.png'], '2'=>'image6.png', '3'=>'image7.png', '4'=>'image8.png', '5'=>'image9.png', '6'=>'image10.png', '7'=>'image11.png', '8'=>'image12.png', '9'=>'image13.png', '10'=>'image18.png', '11'=>'image15.png', '12'=>'image16.png', '13'=>'image17.png', '14'=>'image20.png', '15'=>'image19.png', '16'=>'image21.png', '17'=>'image22.png', '18'=>'image23.png', '19'=>'image24.png', '20'=>'image29.png', '21'=>'image14.png'];$imageReplacements = [];foreach ($feilds as $key=>$feild) {if (is_array($feild)){$pic1_arr = json_decode($picdata['pic'.$key]);foreach ($pic1_arr as $index => $pic1_item) {$imageReplacements[$feild[$index]] = $pic1_item;}}else{$imageReplacements[$feild]=$picdata['pic'.$key];}}$modifier = new PptxXmlModifier();$result = $modifier->createpptx($template, $output, $textReplacements, $imageReplacements);

 

http://www.jsqmd.com/news/869871/

相关文章:

  • 如何在Windows系统上构建专业级游戏控制器虚拟化平台:ViGEmBus终极指南
  • 抖音无水印下载终极指南:3分钟学会免费批量下载高清视频
  • Cloudflare最严验证的合规交互架构:从TLS指纹到Turnstile v3全链路对齐
  • Unity Android构建支持安装失败的根源与解决方案
  • 2026年4月市面上知名的非标定制整列机供应商推荐,市面上诚信的非标定制整列机源头厂家,整列机高速运转性能卓越 - 品牌推荐师
  • Burp Suite快捷键深度解析:上下文敏感操作与肌肉记忆养成
  • ComfyUI节点管理终极指南:如何轻松安装和管理AI工作流插件
  • 微信小游戏序列帧动画实战:Unity2019飞机大战性能优化方案
  • GradCAM原理与PyTorch实战:让CNN模型决策可解释
  • Windows 11安卓子系统完整指南:三步实现跨平台应用体验
  • 靠谱的雅思培训企业解读,环球雅思优势在哪 - mypinpai
  • 温州GEO优化公司排名|2026技术/效果/口碑三维度榜单(2026年5月最新) - GEO排行榜
  • 终极Python金融数据接口:3步掌握免费高效的A股数据获取方案
  • 无需编程的文本分析神器:KH Coder让每个人都能做专业文本挖掘
  • Unity Android构建失败真相:Temp文件夹三重陷阱解析
  • unidbg断点原理与安卓so补环境实战指南
  • 抖音内容批量下载的三大难题,这个开源工具如何一次性解决?
  • Meet Composer:基于控制原语的分层可控文生图架构
  • 海口名表回收探店测评:高价回收靠谱吗?现场对比报价与服务差异 - 奢侈品回收测评
  • 3步掌握Navicat试用重置:macOS数据库管理工具终极指南
  • 携程任我行礼品卡回收攻略:快速变现,简单安全! - 团团收购物卡回收
  • Gemini 1.5、Sora与V-JEPA:AI工程水位线的三大坐标轴
  • 携程任我行礼品卡变现指南:回收这件事你必须知道! - 团团收购物卡回收
  • AI API 401错误排查:密钥存在却报不存在的三层认证解析
  • Unity 2020.3.x下HybridCLR热更新落地实战指南
  • 武汉主流翡翠回收店铺测评:全国连锁机构专业鉴定避坑指南 - 奢侈品回收测评
  • 终极指南:5步掌握Reloaded-II游戏Mod加载器的核心功能
  • Burp Suite登录安全测试实战:从信息泄露到认证加固
  • AI Newsletter实操指南:工程落地、成本优化与防抖提示词设计
  • 如何用开源歌词滚动姬3步制作专业LRC歌词:完全免费跨平台指南