附件系统
Anon Framework 提供统一的附件处理系统 Anon_System_Attachment,支持文件上传、下载、删除、图片处理等功能。
快速开始
基础使用
php
// 上传文件
$result = Anon_System_Attachment::upload('file', 'image');
if ($result['success']) {
echo "文件 ID: " . $result['id'];
echo "访问 URL: " . $result['url'];
}
// 获取附件信息
$attachment = Anon_System_Attachment::getAttachment(123);
// 删除附件
Anon_System_Attachment::delete(123);访问附件
GET /anon/attachment?filetype=image&filename=abc.jpg参数说明:
filetype- 文件类型:image, video, audio, document, otherfilename- 文件名(不含扩展名)imgtype- 可选,图片处理参数
API 参考
上传文件
php
/**
* 上传附件
* @param string $field 表单字段名,默认 'file'
* @param string $fileType 文件类型:image/video/audio/document/other
* @return array ['success'=>bool, 'id'=>int, 'filename'=>string, 'url'=>string]
*/
Anon_System_Attachment::upload(string $field = 'file', string $fileType = 'other'): array示例:
php
// 上传图片
$result = Anon_System_Attachment::upload('avatar', 'image');
// 返回
{
"success": true,
"id": 123,
"filename": "abc123def456.jpg",
"url": "/anon/attachment/image/abc123def456"
}获取附件信息
php
/**
* 获取附件信息
* @param int $id 附件 ID
* @return array|null
*/
Anon_System_Attachment::getAttachment(int $id): ?array示例:
php
$attachment = Anon_System_Attachment::getAttachment(123);
// 返回:
// [
// 'id' => 123,
// 'filename' => 'abc.jpg',
// 'original_name' => 'photo.jpg',
// 'file_size' => 102400,
// 'mime_type' => 'image/jpeg',
// 'created_at' => '2024-01-01 12:00:00'
// ]删除附件
php
/**
* 删除附件(包括文件和数据库记录)
* @param int $id 附件 ID
* @return bool
*/
Anon_System_Attachment::delete(int $id): bool示例:
php
if (Anon_System_Attachment::delete(123)) {
echo "删除成功";
}获取附件列表
php
/**
* 获取附件列表
* @param int $page 页码
* @param int $pageSize 每页数量
* @param string|null $mimeType MIME 类型筛选
* @param string $sort 排序:new=新到老,old=老到新
* @return array ['list'=>[], 'total'=>int]
*/
Anon_System_Attachment::getAttachmentList(int $page = 1, int $pageSize = 20, ?string $mimeType = null, string $sort = 'new'): array示例:
php
// 获取图片列表
$result = Anon_System_Attachment::getAttachmentList(1, 20, 'image');
foreach ($result['list'] as $attachment) {
echo $attachment['filename'];
}生成访问 URL
php
/**
* 获取附件 URL
* @param int $id 附件 ID
* @param string $fileType 文件类型
* @return string
*/
Anon_System_Attachment::getUrl(int $id, string $fileType = 'other'): string示例:
php
$url = Anon_System_Attachment::getUrl(123, 'image');
// 返回:/anon/attachment/image/abc123def456图片处理
Discuz 风格参数
支持在 URL 中添加 imgtype 参数进行图片处理:
格式转换:
/anon/attachment/image/abc?imgtype=webp等比缩放:
/anon/attachment/image/abc?imgtype=672x378转换并缩放:
/anon/attachment/image/abc?imgtype=webp_672x378支持的格式
- 输入格式: jpg, jpeg, png, gif, webp, avif
- 输出格式: jpg, jpeg, png, gif, webp, avif
代码示例
php
// 模板中访问
<img src="/anon/attachment/image/abc?imgtype=webp" alt="WebP 格式">
<img src="/anon/attachment/image/abc?imgtype=300x200" alt="缩略图">
<img src="/anon/attachment/image/abc?imgtype=jpg_800x600" alt="转换并缩放">工具方法
检测文件 MIME 类型
php
$mimeType = Anon_System_Attachment::detectMimeTypeFromFile('/path/to/file.jpg');
// 返回:image/jpeg验证扩展名匹配
php
if (Anon_System_Attachment::isExtensionMatchMimeType('jpg', 'image/jpeg')) {
// 匹配成功
}生成随机文件名
php
$built = Anon_System_Attachment::buildRandomFilename('png');
// 返回:['base' => 'abc123-1234567890', 'filename' => 'abc123-1234567890.png']根据 MIME 获取文件类型
php
$fileType = Anon_System_Attachment::getFileTypeByMime('image/jpeg');
// 返回:'image'管理后台接口
获取附件列表
http
GET /api/cms/admin/attachments请求参数:
page- 页码,默认 1page_size- 每页数量,默认 20,最大 100mime_type- MIME 类型筛选:image, video, audio, documentsort- 排序:new(新到老), old(老到新)
响应示例:
json
{
"code": 0,
"data": {
"list": [
{
"id": 123,
"filename": "abc.jpg",
"name": "原始文件名.jpg",
"url": "/anon/attachment/image/abc",
"mime_type": "image/jpeg",
"size": 102400,
"created_at": 1704067200
}
],
"total": 100,
"page": 1,
"page_size": 20
},
"message": "获取附件列表成功"
}上传附件
http
POST /api/cms/admin/attachments
Content-Type: multipart/form-data
file: [二进制文件]响应示例:
json
{
"code": 0,
"data": {
"id": 123,
"filename": "abc123.jpg",
"original_name": "原始文件名.jpg",
"url": "/anon/attachment/image/abc123",
"mime_type": "image/jpeg",
"file_size": 102400
},
"message": "上传成功"
}删除附件
http
DELETE /api/cms/admin/attachments
Content-Type: application/json
{
"id": 123
}响应示例:
json
{
"code": 0,
"data": null,
"message": "删除成功"
}安全特性
文件类型验证
php
// 自动检测真实 MIME 类型
$realMimeType = Anon_System_Attachment::detectMimeTypeFromFile($tmpPath);
// 验证扩展名与 MIME 类型匹配
if (!Anon_System_Attachment::isExtensionMatchMimeType($ext, $realMimeType)) {
Anon::error("文件类型不匹配");
}文件名安全
- 自动移除危险字符
- 只保留字母、数字、点、连字符、下划线
- 限制长度 255 字符
允许的文件类型
图片: jpg, jpeg, png, gif, webp, bmp, svg, tiff, ico
视频: mp4, avi, mov, wmv, flv, mkv, webm, m4v
音频: mp3, wav, ogg, m4a, aac, flac, wma
文档: pdf, doc, docx, xls, xlsx, ppt, pptx, txt
强缓存机制
附件系统自动添加以下响应头实现强缓存:
http
Cache-Control: public, max-age=315360000
Expires: [10 年后日期]
ETag: "md5 值"
Last-Modified: [文件修改时间]304 协商缓存:
http
If-None-Match: "etag 值"
If-Modified-Since: [日期]最佳实践
1. 前端上传示例
html
<!-- HTML 表单 -->
<form id="uploadForm">
<input type="file" name="file" accept="image/*">
<button type="submit">上传</button>
</form>
<script>
document.getElementById('uploadForm').addEventListener('submit', async (e) => {
e.preventDefault();
const formData = new FormData(e.target);
const response = await fetch('/api/cms/admin/attachments', {
method: 'POST',
body: formData
});
const result = await response.json();
if (result.code === 0) {
console.log('上传成功:', result.data.url);
}
});
</script>2. 批量上传
php
$files = $_FILES['images'];
$results = [];
foreach ($files['name'] as $key => $name) {
$_FILES['single'] = [
'name' => $files['name'][$key],
'type' => $files['type'][$key],
'tmp_name' => $files['tmp_name'][$key],
'error' => $files['error'][$key],
'size' => $files['size'][$key],
];
$results[] = Anon_System_Attachment::upload('single', 'image');
}3. 图片展示优化
html
<!-- 原图 -->
<img src="/anon/attachment/image/abc" alt="原图">
<!-- 缩略图 -->
<img src="/anon/attachment/image/abc?imgtype=200x200" alt="缩略图">
<!-- WebP 格式(更小体积) -->
<img src="/anon/attachment/image/abc?imgtype=webp" alt="WebP">
<!-- 响应式图片 -->
<picture>
<source srcset="/anon/attachment/image/abc?imgtype=webp" type="image/webp">
<img src="/anon/attachment/image/abc" alt="兼容模式">
</picture>常见问题
Q1. 上传失败如何处理?
检查文件类型是否允许,文件大小是否超限:
php
$result = Anon_System_Attachment::upload('file', 'image');
if (!$result['success']) {
echo "错误:" . $result['message'];
}Q2. 如何自定义允许的文件类型?
修改配置文件或数据库中的 upload_allowed_types 选项。
Q3. 图片处理失败怎么办?
确保服务器已安装 GD 扩展:
php
if (!extension_loaded('gd')) {
echo "需要安装 GD 扩展";
}Q4. 如何迁移旧附件数据?
直接操作数据库 attachments 表,确保文件路径正确即可。
