首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >通达OA文件附件处理机制详解

通达OA文件附件处理机制详解

原创
作者头像
企业管理软件开发
发布2026-07-05 18:25:26
发布2026-07-05 18:25:26
1430
举报

一、引言

文件附件处理是OA系统的核心功能之一,涉及文件上传、存储、下载、预览、删除等多个环节。通达OA提供了完善的文件附件处理机制,通过 utility_file.php 文件中的一系列函数实现。本文将深入解析OA的文件附件处理机制,包括上传流程、存储结构、权限控制和最佳实践。

二、文件附件架构总览

2.1 架构设计

图表
图表

2.2 文件存储结构

通达OA的附件存储采用"数据库+文件系统"的架构:

数据库存储

  • 附件元数据(文件名、大小、类型、上传时间等)
  • 附件ID(用于关联业务数据)

文件系统存储

  • 实际文件内容
  • 按模块和日期分目录存储
图表
图表

2.3 附件ID编码机制

OA使用特殊的编码方式生成附件ID:

图表
图表

三、文件上传机制

3.1 upload() - 文件上传函数

代码语言:javascript
复制
upload($field_name, $allow_types = "", $max_size = 0, $module = "", $uid = 0)

功能:处理文件上传

参数说明

参数

类型

默认值

说明

field_name

string

-

文件表单字段名

allow_types

string

""

允许的文件类型

max_size

int

0

最大文件大小(KB),0为不限制

module

string

""

模块名称

uid

int

0

用户ID,默认当前用户

返回值

返回字段

说明

error

错误码(0=成功,其他=失败)

id

附件ID

name

原始文件名

size

文件大小

type

文件类型

path

文件路径

示例

代码语言:javascript
复制
include_once("inc/utility_file.php");

// 处理文件上传
if ($_FILES['attachment']['name']) {
    $result = upload('attachment', '', 20480, 'project');
    
    if ($result['error'] == 0) {
        $attach_id = $result['id'];
        // 保存附件ID到业务表
        $td->query("UPDATE project SET attach_id = '$attach_id' WHERE project_id = 1");
    } else {
        Message(_("上传失败:") . $result['error'], "", "error");
    }
}

3.2 上传流程

图表
图表

3.3 上传表单示例

代码语言:javascript
复制
<form method="post" action="upload.php" enctype="multipart/form-data">
    <input type="file" name="attachment" multiple>
    <button type="submit"><?php echo _("上传"); ?></button>
</form>

注意事项

  • 必须设置 enctype="multipart/form-data"
  • 支持多文件上传(multiple属性)
  • 文件名尽量使用中文

四、附件管理函数

4.1 添加附件

4.1.1 add_attach() - 添加附件

代码语言:javascript
复制
add_attach($module, $record_id, $attach_ids, $uid = 0)

功能:为记录添加附件

参数说明

参数

类型

说明

module

string

模块名称

record_id

int

记录ID

attach_ids

string

附件ID(多个用逗号分隔)

uid

int

用户ID

示例

代码语言:javascript
复制
add_attach('project', 1, '123,456,789');

4.1.2 add_attach_module() - 注册附件模块

代码语言:javascript
复制
add_attach_module($module_name, $module_title)

功能:注册新的附件模块

参数说明

参数

类型

说明

module_name

string

模块名称(英文)

module_title

string

模块标题(中文)

示例

代码语言:javascript
复制
add_attach_module('project', _("项目管理"));

4.2 删除附件

4.2.1 delete_attach() - 删除附件

代码语言:javascript
复制
delete_attach($attach_id)

功能:删除指定附件

参数$attach_id - 附件ID

返回值:true或false

示例

代码语言:javascript
复制
delete_attach('123456');

4.2.2 delete_attach_old() - 删除旧版附件

代码语言:javascript
复制
delete_attach_old($attach_id)

功能:删除旧版附件格式

参数$attach_id - 附件ID

4.3 附件信息获取

4.3.1 attach_size() - 获取附件大小

代码语言:javascript
复制
attach_size($attach_id)

功能:获取附件大小

参数$attach_id - 附件ID

返回值:文件大小(字节)

示例

代码语言:javascript
复制
$size = attach_size('123456');
echo "文件大小:" . format_size($size);

4.3.2 attach_real_path() - 获取附件真实路径

代码语言:javascript
复制
attach_real_path($attach_id)

功能:获取附件在服务器上的真实路径

参数$attach_id - 附件ID

返回值:文件绝对路径

示例

代码语言:javascript
复制
$path = attach_real_path('123456');
echo "文件路径:$path";

4.3.3 attach_url() - 获取附件访问URL

代码语言:javascript
复制
attach_url($attach_id, $inline = false)

功能:获取附件的访问URL

参数说明

参数

类型

说明

attach_id

string

附件ID

inline

bool

是否在线预览(true=预览,false=下载)

返回值:附件URL

示例

代码语言:javascript
复制
// 获取下载链接
$download_url = attach_url('123456');

// 获取预览链接
$preview_url = attach_url('123456', true);

4.3.4 attach_link() - 获取附件链接

代码语言:javascript
复制
attach_link($attach_id, $text = "", $inline = false)

功能:生成完整的附件链接HTML

参数说明

参数

类型

说明

attach_id

string

附件ID

text

string

链接文字,默认文件名

inline

bool

是否在线预览

返回值:HTML链接代码

示例

代码语言:javascript
复制
echo attach_link('123456', _("点击下载"));

4.4 附件操作

4.4.1 copy_attach() - 复制附件

代码语言:javascript
复制
copy_attach($attach_id, $new_module = "", $new_record_id = 0)

功能:复制附件到新位置

参数说明

参数

类型

说明

attach_id

string

附件ID

new_module

string

新模块名称

new_record_id

int

新记录ID

返回值:新附件ID

示例

代码语言:javascript
复制
$new_attach_id = copy_attach('123456', 'project', 2);

4.4.2 attach_sign_key() - 生成附件签名

代码语言:javascript
复制
attach_sign_key($attach_id)

功能:生成附件访问签名

参数$attach_id - 附件ID

返回值:签名字符串

用途:用于生成安全的附件访问链接

示例

代码语言:javascript
复制
$sign = attach_sign_key('123456');
$url = "download.php?id=123456&sign=$sign";

4.4.3 attach_id_encode() / attach_id_decode() - ID编解码

代码语言:javascript
复制
// 编码
$encoded_id = attach_id_encode($raw_id);

// 解码
$raw_id = attach_id_decode($encoded_id);

功能:附件ID的加密和解密

参数$raw_id / $encoded_id - 原始ID或编码后的ID

用途:防止附件ID被猜测

五、文件类型判断函数

5.1 文件类型检测

5.1.1 is_uploadable() - 是否可上传

代码语言:javascript
复制
is_uploadable($filename)

功能:判断文件是否允许上传

参数$filename - 文件名

返回值:true或false

5.1.2 is_text() - 是否为文本文件

代码语言:javascript
复制
is_text($filename)

功能:判断文件是否为文本文件

参数$filename - 文件名

返回值:true或false

5.1.3 is_office() - 是否为Office文件

代码语言:javascript
复制
is_office($filename)

功能:判断文件是否为Office文件

参数$filename - 文件名

返回值:true或false

支持格式:doc, docx, xls, xlsx, ppt, pptx, pdf等

5.1.4 is_image() - 是否为图片文件

代码语言:javascript
复制
is_image($filename)

功能:判断文件是否为图片文件

参数$filename - 文件名

返回值:true或false

支持格式:jpg, jpeg, png, gif, bmp等

5.1.5 is_viewable() - 是否可在线预览

代码语言:javascript
复制
is_viewable($filename)

功能:判断文件是否支持在线预览

参数$filename - 文件名

返回值:true或false

支持格式:图片、Office文档、PDF等

5.1.6 is_media() - 是否为媒体文件

代码语言:javascript
复制
is_media($filename)

功能:判断文件是否为媒体文件

参数$filename - 文件名

返回值:true或false

支持格式:mp3, mp4, avi, flv等

5.1.7 is_editable() - 是否可编辑

代码语言:javascript
复制
is_editable($filename)

功能:判断文件是否支持在线编辑

参数$filename - 文件名

返回值:true或false

5.1.8 is_wps() - 是否为WPS文件

代码语言:javascript
复制
is_wps($filename)

功能:判断文件是否为WPS格式

参数$filename - 文件名

返回值:true或false

5.2 文件类型判断流程图

图表
图表

六、图片处理函数

6.1 CreateThumb() - 创建缩略图

代码语言:javascript
复制
CreateThumb($src_file, $dst_file, $max_width, $max_height)

功能:创建图片缩略图

参数说明

参数

类型

说明

src_file

string

源文件路径

dst_file

string

目标文件路径

max_width

int

最大宽度

max_height

int

最大高度

返回值:true或false

示例

代码语言:javascript
复制
CreateThumb(
    "attach/project/202401/image.jpg",
    "attach/project/202401/image_thumb.jpg",
    200,
    200
);

6.2 image_mimetype() - 获取图片MIME类型

代码语言:javascript
复制
image_mimetype($filename)

功能:获取图片的MIME类型

参数$filename - 文件名

返回值:MIME类型字符串

示例

代码语言:javascript
复制
$mime = image_mimetype("image.jpg");
echo "MIME类型:$mime"; // 输出:image/jpeg

6.3 ReplaceImageSrc() - 替换图片路径

代码语言:javascript
复制
ReplaceImageSrc($html, $module, $record_id)

功能:替换HTML内容中的图片路径为附件URL

参数说明

参数

类型

说明

html

string

HTML内容

module

string

模块名称

record_id

int

记录ID

返回值:处理后的HTML

示例

代码语言:javascript
复制
$content = '<img src="image.jpg">';
$content = ReplaceImageSrc($content, 'project', 1);
// 输出:<img src="/attach/project/202401/image.jpg">

七、文件操作函数

7.1 目录操作

7.1.1 dir_size() - 计算目录大小

代码语言:javascript
复制
dir_size($dir)

功能:计算目录占用空间大小

参数$dir - 目录路径

返回值:目录大小(字节)

示例

代码语言:javascript
复制
$size = dir_size("attach/project");
echo "目录大小:" . format_size($size);

7.1.2 delete_dir() - 删除目录

代码语言:javascript
复制
delete_dir($dir)

功能:删除目录及其所有内容

参数$dir - 目录路径

返回值:true或false

7.1.3 dir_file_nums() - 统计目录文件数

代码语言:javascript
复制
dir_file_nums($dir)

功能:统计目录中的文件数量

参数$dir - 目录路径

返回值:文件数量

7.2 文件操作

7.2.1 backup_file() - 备份文件

代码语言:javascript
复制
backup_file($src_file, $dst_file)

功能:备份文件

参数说明

参数

类型

说明

src_file

string

源文件路径

dst_file

string

目标文件路径

返回值:true或false

7.2.2 td_copy() - 文件复制

代码语言:javascript
复制
td_copy($src_file, $dst_file)

功能:复制文件

参数说明

参数

类型

说明

src_file

string

源文件路径

dst_file

string

目标文件路径

返回值:true或false

7.2.3 td_rename() - 文件重命名

代码语言:javascript
复制
td_rename($old_name, $new_name)

功能:重命名文件

参数说明

参数

类型

说明

old_name

string

旧文件名

new_name

string

新文件名

返回值:true或false

7.2.4 td_file_put_contents() - 写入文件

代码语言:javascript
复制
td_file_put_contents($file, $content)

功能:写入文件内容

参数说明

参数

类型

说明

file

string

文件路径

content

string

文件内容

返回值:写入的字节数或false

八、附件处理实战

8.1 完整的附件上传示例

代码语言:javascript
复制
<?php
include_once("inc/auth.inc.php");
include_once("inc/header.inc.php");
include_once("inc/utility_file.php");

if ($_POST) {
    $attach_ids = array();
    
    // 处理文件上传
    if ($_FILES['attachments']['name'][0]) {
        foreach ($_FILES['attachments']['name'] as $key => $name) {
            // 临时修改$_FILES结构
            $temp_file = array(
                'name' => $_FILES['attachments']['name'][$key],
                'type' => $_FILES['attachments']['type'][$key],
                'tmp_name' => $_FILES['attachments']['tmp_name'][$key],
                'error' => $_FILES['attachments']['error'][$key],
                'size' => $_FILES['attachments']['size'][$key]
            );
            
            $_FILES['attachment'] = $temp_file;
            
            $result = upload('attachment', '', 20480, 'project');
            
            if ($result['error'] == 0) {
                $attach_ids[] = $result['id'];
            }
        }
    }
    
    // 保存到数据库
    if (!empty($attach_ids)) {
        $attach_id_str = implode(',', $attach_ids);
        $td->query("INSERT INTO project_attach (project_id, attach_ids) VALUES (1, '$attach_id_str')");
    }
    
    Message(_("上传成功"), "index.php", "success");
    exit;
}
?>

<form method="post" enctype="multipart/form-data">
    <input type="file" name="attachments" multiple>
    <button type="submit"><?php echo _("上传附件"); ?></button>
</form>

<?php
include_once("inc/footer.inc.php");
?>

8.2 附件列表展示示例

代码语言:javascript
复制
<?php
include_once("inc/auth.inc.php");
include_once("inc/header.inc.php");
include_once("inc/utility_file.php");

// 获取附件列表
$result = $td->query("SELECT attach_ids FROM project WHERE project_id = 1");
$row = $td->fetch_array($result);
$attach_ids = explode(',', $row['attach_ids']);
?>

<div class="attach-list">
    <h3><?php echo _("附件列表"); ?></h3>
    <?php foreach ($attach_ids as $attach_id) { ?>
        <div class="attach-item">
            <?php echo attach_link($attach_id); ?>
            <span class="size">(<?php echo format_size(attach_size($attach_id)); ?>)</span>
            <a href="delete_attach.php?id=<?php echo $attach_id; ?>" 
               onclick="return confirm('<?php echo _('确定删除?'); ?>')">
                <?php echo _("删除"); ?>
            </a>
        </div>
    <?php } ?>
</div>

<?php
include_once("inc/footer.inc.php");
?>

8.3 附件权限控制

代码语言:javascript
复制
<?php
include_once("inc/auth.inc.php");

// 检查附件权限
function check_attach_permission($attach_id, $uid) {
    global $td;
    
    // 查询附件所属记录
    $sql = "SELECT * FROM project_attach WHERE attach_ids LIKE '%$attach_id%'";
    $result = $td->query($sql);
    
    if ($td->num_rows($result) > 0) {
        $row = $td->fetch_array($result);
        
        // 检查项目权限
        $project_result = $td->query("SELECT creator_uid FROM project WHERE project_id = " . $row['project_id']);
        $project_row = $td->fetch_array($project_result);
        
        if ($project_row['creator_uid'] == $uid || is_module_manager($uid, 'project')) {
            return true;
        }
    }
    
    return false;
}

// 使用示例
$attach_id = $_GET['id'];
if (!check_attach_permission($attach_id, $_SESSION['uid'])) {
    Message(_("无权限访问该附件"), "", "error");
    exit;
}

// 允许访问附件
$path = attach_real_path($attach_id);
// 输出文件内容
?>

九、最佳实践

9.1 安全注意事项

图表
图表

安全建议

安全项

建议

文件类型

使用白名单机制,只允许上传已知安全的文件类型

文件大小

设置合理的大小限制,防止DoS攻击

文件名

过滤特殊字符,避免路径遍历攻击

权限控制

验证用户是否有权限访问附件

文件归属

检查附件是否属于用户有权访问的记录

9.2 性能优化

图表
图表

优化建议

优化项

建议

存储结构

按模块和日期分目录存储,便于管理和清理

缓存策略

缓存附件元数据,减少数据库查询

CDN加速

使用CDN加速附件下载

文件压缩

对图片和文档进行压缩处理

清理策略

定期清理过期或无用的附件

9.3 备份策略

图表
图表

备份建议

备份项

说明

数据库

备份附件表和关联业务表

文件系统

备份MYOA\attach目录

增量备份

只备份新增和修改的文件

恢复测试

定期测试备份文件的可用性

十、常见问题

10.1 上传失败

现象:文件上传失败,返回错误码

解决方案

图表
图表

错误码说明

错误码

原因

解决方案

1

文件大小超过PHP配置限制

修改php.ini中的upload_max_filesize

2

文件类型不在白名单

修改allow_types参数

3

服务器磁盘空间不足

清理磁盘空间

4

临时目录无写入权限

检查临时目录权限

10.2 附件无法下载

现象:点击附件链接无法下载

解决方案

问题类型

排查方法

附件ID错误

检查attach_id是否正确

文件已删除

检查文件是否存在于attach目录

权限不足

检查用户权限

路径错误

使用attach_real_path()验证路径

10.3 附件预览异常

现象:Office文件无法在线预览

解决方案

问题类型

排查方法

OC服务未启动

检查Office_OC服务状态

文件格式不支持

检查是否为支持的格式

文件损坏

验证文件完整性

内存不足

增加MemoryMax配置

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

目录
  • 一、引言
  • 二、文件附件架构总览
    • 2.1 架构设计
    • 2.2 文件存储结构
    • 2.3 附件ID编码机制
  • 三、文件上传机制
    • 3.1 upload() - 文件上传函数
    • 3.2 上传流程
    • 3.3 上传表单示例
  • 四、附件管理函数
    • 4.1 添加附件
    • 4.2 删除附件
    • 4.3 附件信息获取
    • 4.4 附件操作
  • 五、文件类型判断函数
    • 5.1 文件类型检测
    • 5.2 文件类型判断流程图
  • 六、图片处理函数
    • 6.1 CreateThumb() - 创建缩略图
    • 6.2 image_mimetype() - 获取图片MIME类型
    • 6.3 ReplaceImageSrc() - 替换图片路径
  • 七、文件操作函数
    • 7.1 目录操作
    • 7.2 文件操作
  • 八、附件处理实战
    • 8.1 完整的附件上传示例
    • 8.2 附件列表展示示例
    • 8.3 附件权限控制
  • 九、最佳实践
    • 9.1 安全注意事项
    • 9.2 性能优化
    • 9.3 备份策略
  • 十、常见问题
    • 10.1 上传失败
    • 10.2 附件无法下载
    • 10.3 附件预览异常
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档