子辰聊天室1.2.0.0发布了!
发布页: https://bri6.cn/archives/405.html
开源主仓库: https://github.com/XiaoFeng-QWQ/zicheng-web-chat-room
开源镜像: https://gitee.com/XiaoFengQWQ/zichen-web-chat-room (可能不保证实时更新)
更改:
- 聊天支持上传文件,指令列表新增投票
- 部分CSS、布局优化
- 优化部分代码
实现方法:
支持文件上传:
1. 检查文件是否上传成功
if (isset($_FILES['file']) && $_FILES['file']['error'] === UPLOAD_ERR_OK) {
isset($_FILES['file'])
: 检查是否存在上传的文件。$_FILES['file']['error'] === UPLOAD_ERR_OK
: 检查文件上传是否成功,UPLOAD_ERR_OK
表示没有错误发生。$_FILES['file']['error']
是文件上传的错误码。
2. 获取文件的 MIME 类型
$fileType = mime_content_type($_FILES['file']['tmp_name']);
mime_content_type($_FILES['file']['tmp_name'])
:通过mime_content_type
函数获取文件的 MIME 类型。该函数根据文件内容而不是文件扩展名来判断文件类型。
3. 检查文件的 MIME 类型是否在允许范围内
$allowed = false;
if (in_array($fileType, $chatConfig->uploadFile['allowTypes'])) {
$allowed = true;
}
if (!$allowed) {
respondWithJson(ChatController::STATUS_WARNING, '无效的文件类型');
}
$chatConfig->uploadFile['allowTypes']
:这是一个允许的文件类型列表(通常是数组),可能包含诸如'image/jpeg'
,'image/png'
等类型。in_array($fileType, $chatConfig->uploadFile['allowTypes'])
:检查文件的 MIME 类型是否在允许的类型数组中。- 如果文件类型不被允许,返回一个警告信息
'无效的文件类型'
。
4. 检查文件的大小是否超过限制
if ($_FILES['file']['size'] > $chatConfig->uploadFile['maxSize']) {
respondWithJson(ChatController::STATUS_WARNING, '文件太大');
}
$_FILES['file']['size']
:获取上传文件的大小(单位字节)。$chatConfig->uploadFile['maxSize']
:最大文件大小限制。- 如果文件大小超出了限制,返回
'文件太大'
的警告信息。
5. 创建上传目录(如果不存在)
$uploadDir = FRAMEWORK_DIR . "/StaticResources/uploads/" . date('Y/m/d') . "/u_{$userInfo['user_id']}/";
if (!is_dir($uploadDir) && !mkdir($uploadDir, 0777, true)) {
respondWithJson(ChatController::STATUS_ERROR, '无法创建上传目录');
}
- 通过当前日期(年、月、日)来组织上传文件的目录结构:
/StaticResources/uploads/Y/m/d/u_user_id/
。 is_dir($uploadDir)
: 检查目录是否存在。mkdir($uploadDir, 0777, true)
: 如果目录不存在,创建该目录,权限为0777
,true
表示递归创建不存在的目录。- 如果创建失败,返回错误信息
'无法创建上传目录'
。
6. 生成唯一的文件名并保存文件
$fileName = time() . "_" . uniqid() . '.' . pathinfo($_FILES['file']['name'], PATHINFO_EXTENSION);
$filePath = $uploadDir . $fileName;
if (!move_uploaded_file($_FILES['file']['tmp_name'], $filePath)) {
respondWithJson(ChatController::STATUS_ERROR, '上传失败');
}
time() . "_" . uniqid()
:使用当前时间戳和一个唯一 ID 生成文件名,确保文件名不重复。pathinfo($_FILES['file']['name'], PATHINFO_EXTENSION)
:获取上传文件的扩展名。move_uploaded_file($_FILES['file']['tmp_name'], $filePath)
:将文件从临时目录移动到指定的目标路径。- 如果文件上传失败,返回
'上传失败'
的错误信息。
7. 生成文件的相对路径
$relativeImagePath = $helpres->getCurrentUrl() . "/StaticResources/uploads/" . date('Y/m/d') . "/u_{$userInfo['user_id']}/$fileName";
- 生成文件的相对 URL 路径,用于在前端显示或下载文件。
$helpres->getCurrentUrl()
获取当前的基础 URL。
8. 生成文件信息模板
function generateFileTemplate($fileData)
{
$template = '[!file(';
foreach ($fileData as $key => $value) {
$template .= $key . '="' . $value . '", ';
}
$template = rtrim($template, ', ');
$template .= ')]';
return $template;
}
- 这是一个用于生成文件信息模板的函数。它会将传入的文件数据(如路径、名称、类型、大小等)转化为特定的模板格式,最终返回
[!file(path="xxx", name="xxx", type="xxx", size="xxx", download="true")]
这样的格式。
9. 构建文件信息并添加到消息中
$message .= generateFileTemplate([
'path' => $relativeImagePath,
'name' => $_FILES['file']['name'],
'type' => $_FILES['file']['type'],
'size' => round($_FILES['file']['size'] / 1024, 2) . 'KB',
'download' => 'true'
]);
10. 解析
/**
* 解析文件模板字符串,提取其中的文件参数。
*
* @param {string} template - 文件模板字符串,格式应为 [!file(key1="value1", key2="value2", ...)]
* @returns {Object|null} - 返回一个包含文件参数的对象,如果模板格式不匹配,返回 null。
*/
function parseFileTemplate(template) {
// 定义正则表达式,用于匹配模板字符串中的内容
const pattern = /\[!file\((.*?)\)\]/;
// 使用正则表达式匹配模板字符串
const match = template.match(pattern);
// 如果匹配成功
if (match) {
// 获取括号内的参数部分,match[1] 是正则匹配到的第一个捕获组
const paramsString = match[1];
// 将参数字符串分割成单个参数,格式为 key=value
const params = paramsString.split(',').reduce((acc, param) => {
// 分割每个参数为 key 和 value
const [key, value] = param.split('=');
// 去除键值对两端的空白字符,去除值两端的引号
acc[key.trim()] = value.trim().replace(/^"|"$/g, '');
return acc;
}, {}); // 初始值为空对象,用于存储解析后的参数
// 返回解析出的参数对象
return params;
}
// 如果没有匹配到符合格式的模板,返回 null
return null;
}
样式优化
{tabs}
{tabs-pane label="前台样式优化"}
{/tabs-pane}
{tabs-pane label="后台部分布局优化"}
{/tabs-pane}
{/tabs}