- 获取当前文章附件的大小:即文章内容中通过
{dede:field name='body'/}标签引用的附件。 - 获取附件表 (
#@__uploads) 中指定附件的大小:即直接从数据库的附件表中查询某个附件的文件大小。
下面我将分别详细介绍这两种方法,并提供代码示例。
获取当前文章附件的大小(通过正则表达式解析)
这种方法适用于在文章内容页 (article_article.htm) 中,解析文章正文 (body 字段) 里的 <a> 或 <img> 标签,并计算其中附件的总大小。
核心思路:
- 获取当前文章的
body- 使用正则表达式匹配出所有附件的路径。
- 根据附件路径,从数据库的
#@__uploads表中查询出每个附件的大小。- 将所有附件的大小累加,并进行格式化(如 KB, MB)。
实现步骤:
页模板 (article_article.htm) 中添加代码
在你需要显示附件总大小的位置,加入以下 PHP 代码:
<?php
// 获取当前文章的ID
$aid = $arcID;
// 获取文章内容
$body = $fields['body'];
// 引入数据库配置文件,确保能连接到数据库
// 如果是在PHP标签内,通常已经可以访问 $db 对象,织梦框架会自动处理
// 正则表达式匹配出所有附件的路径,兼容 /uploads/ 和 ../uploads/ 等路径
$pattern = '/\/(uploads|templets|a|special)\/.*?\.(rar|zip|doc|docx|pdf|txt|jpg|jpeg|png|gif|mp3|mp4|flv|exe)/i';
preg_match_all($pattern, $body, $matches);
$totalSize = 0;
if (!empty($matches[0])) {
// 将匹配到的所有路径去重,避免重复计算
$uniqueFiles = array_unique($matches[0]);
// 拼接IN查询的ID列表,注意要去掉路径前面的斜杠
$fileUrls = array_map(function($url) {
// 织梦附件表中存储的是url字段,我们通过url来匹配
return addslashes(trim($url, '/'));
}, $uniqueFiles);
if (!empty($fileUrls)) {
$fileUrlsStr = "('" . implode("','", $fileUrls) . "')";
// 查询附件表
$query = "SELECT url, size FROM `#@__uploads` WHERE url IN {$fileUrlsStr}";
$attachArray = $dsql->GetAll($query);
if (!empty($attachArray)) {
foreach ($attachArray as $attach) {
$totalSize += $attach['size'];
}
}
}
}
// 格式化文件大小
function formatSize($size)
{
$units = array(' B', ' KB', ' MB', ' GB', ' TB');
for ($i = 0; $size >= 1024 && $i < 4; $i++) {
$size /= 1024;
}
return round($size, 2) . $units[$i];
}
// 输出结果
if ($totalSize > 0) {
echo "附件总大小: " . formatSize($totalSize);
} else {
echo "该文章无附件";
}
?>
代码解释:
$fields['body']: 获取文章的正文内容。preg_match_all: 使用正则表达式从正文中提取所有附件的完整路径。array_unique: 对提取到的路径进行去重,防止一个附件在文章中出现多次而被重复计算。$dsql->GetAll(...): 执行SQL查询,从#@__uploads表中获取所有匹配附件的size。formatSize(): 一个辅助函数,用于将字节大小转换为更易读的 KB、MB 等格式。
获取指定附件的大小(通过附件ID或路径)
这种方法更通用,不局限于当前文章,你可以知道任何一个附件的 ID 或其存储路径,然后直接获取它的大小。
核心思路:
直接对 #@__uploads 数据表进行查询,通过 aid (附件ID) 或 url (附件路径) 来定位附件,并读取其 size 字段。
实现步骤:
场景A:通过附件ID (aid) 获取大小
假设你有一个附件的 ID 是 123。
<?php
$attach_id = 123; // 假设这是你要查询的附件ID
// 查询数据库
$attachRow = $dsql->GetOne("SELECT size FROM `#@__uploads` WHERE aid = '{$attach_id}'");
if (is_array($attachRow)) {
$size = $attachRow['size'];
echo "附件ID为 {$attach_id} 的大小是: " . formatSize($size);
} else {
echo "未找到ID为 {$attach_id} 的附件";
}
// 复用上面的格式化函数
function formatSize($size)
{
$units = array(' B', ' KB', ' MB', ' GB', ' TB');
for ($i = 0; $size >= 1024 && $i < 4; $i++) {
$size /= 1024;
}
return round($size, 2) . $units[$i];
}
?>
场景B:通过附件路径 (url) 获取大小
假设你有一个附件的相对路径是 uploads/2025/10/25/a_file.zip。
<?php
$attach_url = 'uploads/2025/10/25/a_file.zip'; // 假设这是你要查询的附件路径
// 为了安全,对路径进行转义
$attach_url_safe = addslashes($attach_url);
// 查询数据库
$attachRow = $dsql->GetOne("SELECT size FROM `#@__uploads` WHERE url = '{$attach_url_safe}'");
if (is_array($attachRow)) {
$size = $attachRow['size'];
echo "路径为 {$attach_url} 的附件大小是: " . formatSize($size);
} else {
echo "未找到路径为 {$attach_url} 的附件";
}
// 复用上面的格式化函数
function formatSize($size)
{
$units = array(' B', ' KB', ' MB', ' GB', ' TB');
for ($i = 0; $size >= 1024 && $i < 4; $i++) {
$size /= 1024;
}
return round($size, 2) . $units[$i];
}
?>
总结与注意事项
| 方法 | 适用场景 | 优点 | 缺点 |
|---|---|---|---|
| 方法一 (正则解析) | 在文章列表页或内容页,动态计算当前文章所有附件的总和。 | 灵活,能自动适应文章内容变化。 | 性能开销较大,需要多次数据库查询(如果附件多),且依赖正则表达式的准确性。 |
| 方法二 (直接查询) | 知道附件ID或路径,需要精确获取单个或多个附件的大小。 | 速度快,查询精准,不依赖内容解析。 | 需要预先知道附件的ID或路径,不够动态。 |
重要提示:
- 数据库前缀:如果你的数据库表前缀不是
#@__,请将其替换为你的实际前缀(如dede_)。 $dsql对象:在 DedeCMS 的模板文件中,$dsql全局数据库对象通常是可用的,但在自定义函数或复杂逻辑中,可能需要手动引入或确保其作用域。- 安全性:当使用用户输入(如ID或路径)来构造SQL查询时,务必使用
addslashes()或 DedeCMS 提供的安全函数进行转义,防止SQL注入。 - 附件表结构:
#@__uploads表的核心字段是aid(附件ID),url(附件路径),title(附件标题),filesize(文件大小,有时也叫size),请确保你的表结构与代码一致。
