WordPress按扩展名打包文件为zip下载时包内含HTML代码问题
问题根因
你下载的zip里混HTML是三个核心问题导致的:
- 代码执行时机不对:你把下载逻辑直接嵌在页面模板里,等代码跑到输出文件的步骤时,WordPress已经把页面头部、正文的HTML内容输出到返回流里了,这些内容会被拼在zip文件内容前面,解压当然会报错,用记事本打开就能看到提前输出的HTML。
- 路径拼接错误:你取的
$dir变量末尾没有目录分隔符,拼文件路径的时候会变成/autoinstalator/wordpress/wp-content/uploadsxxx.3ds,根本找不到目标文件,实际生成的zip是空的。 - 没有做输出缓冲清理、临时文件处理,不仅容易坏包,还会把生成的zip存在站点公开目录下,有安全隐患。
修复方案
直接替换成下面的代码,逻辑已经适配WordPress运行机制:
<?php // 下载逻辑挂载到init钩子,在所有页面内容输出前执行 add_action('init', function() { if (!isset($_POST['3dsdownload'])) return; // 补全目录末尾的分隔符,避免路径拼接错误 $target_dir = trailingslashit(realpath("/autoinstalator/wordpress/wp-content/uploads/")); $file_list = array_diff(scandir($target_dir), ['.', '..']); // 压缩包存在系统临时目录,不落地到站点公开路径 $temp_zip_path = tempnam(sys_get_temp_dir(), '3ds_pack_'); $zip = new ZipArchive(); if ($zip->open($temp_zip_path, ZipArchive::CREATE) !== true) { wp_die('压缩包创建失败,请检查目录权限'); } foreach ($file_list as $file) { $full_path = $target_dir . $file; // 跳过子目录 if (is_dir($full_path)) continue; // 大小写不敏感匹配扩展名 $ext = strtolower(pathinfo($full_path, PATHINFO_EXTENSION)); if ($ext === '3ds') { $zip->addFile($full_path, basename($full_path)); } } $zip->close(); // 清空所有提前输出的内容,杜绝HTML混进压缩包 while (ob_get_level()) ob_end_clean(); // 补全下载响应头 header('Content-Type: application/zip'); header('Content-Disposition: attachment; filename="3ds.zip"'); header('Content-Length: ' . filesize($temp_zip_path)); header('Pragma: no-cache'); header('Expires: 0'); // 输出文件后立即删除临时压缩包 readfile($temp_zip_path); unlink($temp_zip_path); exit; }); ?> <!-- 页面内的表单直接保留即可 --> <form method="post"> <input type="submit" name="3dsdownload" value="下载3DS格式资源包"/> </form>
扩展说明
- 要做另外两个对应其他扩展名的按钮,直接复制上面的
add_action逻辑块,修改$_POST的判断字段、匹配的扩展名、输出的文件名即可,注意临时文件前缀不要重复,避免冲突。 - 当前逻辑和你原有代码一致,只扫描uploads根目录下的文件,如果需要递归扫描所有子目录的对应格式文件,把
scandir的逻辑换成递归目录遍历即可。 - 不要把生成的压缩包存在站点根目录、uploads目录等公开可访问的路径,避免被未授权的用户爬取,占用服务器存储空间。
内容的提问来源于stack exchange,提问作者Dark Floyd
相关产品推荐
相关产品推荐

