feat(WebSocket): 添加数据库连接检查和文件预览功能
- 在DefaultWebSocketController中添加数据库连接检查功能 - 实现文件预览和下载功能及相关API接口 - 更新测试页面支持文件预览和下载操作 - 移除旧的数据库维护子进程机制,改为函数检查 - 在构建请求数据时添加文件字段支持
This commit is contained in:
@@ -112,8 +112,15 @@ class WebSocket extends WebSocketBase
|
||||
return;
|
||||
}
|
||||
|
||||
// 处理文件预览
|
||||
if (isset($data['action']) && $data['action'] === 'file_preview') {
|
||||
$this->handleFilePreview($conn, $data);
|
||||
return;
|
||||
}
|
||||
|
||||
$conn->send(json_encode(['type' => 'error', 'message' => 'Unknown action']));
|
||||
|
||||
|
||||
} catch (\Exception $e) {
|
||||
$conn->send(json_encode(['type' => 'error', 'message' => $e->getMessage(), 'line' => $e->getLine(), 'file' => $e->getFile(), 'trace' => $e->getTraceAsString()]));
|
||||
}
|
||||
@@ -268,7 +275,7 @@ class WebSocket extends WebSocketBase
|
||||
$enable_stream = $stream || $response_mode == 'streaming';
|
||||
|
||||
// 构建请求数据和请求头
|
||||
$requestData = $this->buildRequestData($query, $user_id, $conversation_id, $enable_stream);
|
||||
$requestData = $this->buildRequestData($query, $user_id, $conversation_id, $enable_stream, $data);
|
||||
$headers = $this->buildRequestHeaders($config['api_key']);
|
||||
|
||||
// 发送请求到Dify API
|
||||
@@ -299,7 +306,7 @@ class WebSocket extends WebSocketBase
|
||||
try {
|
||||
// 获取客户端信息
|
||||
$clientInfo = $this->clientData[$conn->resourceId];
|
||||
|
||||
|
||||
// 获取分片上传相关参数
|
||||
$file_id = $data['file_id'] ?? '';
|
||||
$file_name = $data['file_name'] ?? '';
|
||||
@@ -358,7 +365,7 @@ class WebSocket extends WebSocketBase
|
||||
try {
|
||||
// 获取客户端信息
|
||||
$clientInfo = $this->clientData[$conn->resourceId];
|
||||
|
||||
|
||||
// 获取合并相关参数
|
||||
$file_id = $data['file_id'] ?? '';
|
||||
$file_name = $data['file_name'] ?? '';
|
||||
@@ -485,17 +492,17 @@ class WebSocket extends WebSocketBase
|
||||
$this->cleanupTempFiles($temp_dir);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 解析错误信息
|
||||
$errorMessage = $e->getMessage();
|
||||
$errorCode = 500;
|
||||
$errorType = 'upload_failed';
|
||||
|
||||
|
||||
// 提取HTTP错误码和Dify错误信息
|
||||
if (preg_match('/HTTP请求失败,状态码:(\d+),响应:(.*)/', $errorMessage, $matches)) {
|
||||
$errorCode = (int)$matches[1];
|
||||
$errorCode = (int) $matches[1];
|
||||
$errorResponse = $matches[2];
|
||||
|
||||
|
||||
try {
|
||||
$errorData = json_decode($errorResponse, true);
|
||||
if (isset($errorData['code'])) {
|
||||
@@ -508,7 +515,7 @@ class WebSocket extends WebSocketBase
|
||||
// 解析失败,使用原始错误信息
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$conn->send(json_encode([
|
||||
'type' => 'error',
|
||||
'code' => $errorCode,
|
||||
@@ -555,7 +562,7 @@ class WebSocket extends WebSocketBase
|
||||
try {
|
||||
// 获取客户端信息
|
||||
$clientInfo = $this->clientData[$conn->resourceId];
|
||||
|
||||
|
||||
// 获取检查相关参数
|
||||
$file_id = $data['file_id'] ?? '';
|
||||
$total_chunks = $data['total_chunks'] ?? 0;
|
||||
@@ -606,6 +613,144 @@ class WebSocket extends WebSocketBase
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理文件预览
|
||||
* @param ConnectionInterface $conn
|
||||
* @param array $data
|
||||
*/
|
||||
private function handleFilePreview(ConnectionInterface $conn, $data)
|
||||
{
|
||||
try {
|
||||
// 获取客户端信息
|
||||
$clientInfo = $this->clientData[$conn->resourceId];
|
||||
|
||||
// 获取预览相关参数
|
||||
$file_id = $data['file_id'] ?? '';
|
||||
$as_attachment = $data['as_attachment'] ?? false;
|
||||
$user_id = $data['user_id'] ?? $clientInfo['user_id'];
|
||||
$site_id = $data['uniacid'] ?? $clientInfo['site_id'];
|
||||
$token = $data['token'] ?? $clientInfo['token'];
|
||||
|
||||
// 验证参数
|
||||
if (empty($file_id)) {
|
||||
throw new \Exception('文件ID不能为空');
|
||||
}
|
||||
|
||||
// 验证参数并获取配置,与 Kefu.php 保持一致
|
||||
$config = $this->validateAndGetConfig([
|
||||
'file_id' => ['required' => true, 'message' => '文件ID不能为空', 'description' => '文件ID'],
|
||||
'user_id' => ['required' => true, 'message' => '请求参数 `user_id` 不能为空', 'description' => '用户ID']
|
||||
], [
|
||||
'file_id' => $file_id,
|
||||
'user_id' => $user_id,
|
||||
'uniacid' => $site_id,
|
||||
'token' => $token
|
||||
]);
|
||||
|
||||
// 构建请求URL
|
||||
$url = $config['base_url'] . '/files/' . $file_id . '/preview';
|
||||
if ($as_attachment) {
|
||||
$url .= '?as_attachment=true';
|
||||
}
|
||||
|
||||
// 构建请求头
|
||||
$headers = [
|
||||
'Authorization: Bearer ' . $config['api_key'],
|
||||
'Accept: */*'
|
||||
];
|
||||
|
||||
// 发送请求到Dify API
|
||||
$response = $this->curlGetFile($url, $headers);
|
||||
|
||||
// 发送预览成功响应
|
||||
$conn->send(json_encode([
|
||||
'type' => 'file_preview_success',
|
||||
'file_id' => $file_id,
|
||||
'file_url' => $url,
|
||||
'message' => '文件预览请求成功'
|
||||
]));
|
||||
|
||||
$this->log('文件预览请求成功,文件ID:' . $file_id, 'info');
|
||||
|
||||
} catch (\Exception $e) {
|
||||
// 解析错误信息
|
||||
$errorMessage = $e->getMessage();
|
||||
$errorCode = 500;
|
||||
$errorType = 'preview_failed';
|
||||
|
||||
// 提取HTTP错误码和Dify错误信息
|
||||
if (preg_match('/HTTP请求失败,状态码:(\d+),响应:(.*)/', $errorMessage, $matches)) {
|
||||
$errorCode = (int) $matches[1];
|
||||
$errorResponse = $matches[2];
|
||||
|
||||
try {
|
||||
$errorData = json_decode($errorResponse, true);
|
||||
if (isset($errorData['code'])) {
|
||||
$errorType = $errorData['code'];
|
||||
}
|
||||
if (isset($errorData['message'])) {
|
||||
$errorMessage = $errorData['message'];
|
||||
}
|
||||
} catch (\Exception $decodeEx) {
|
||||
// 解析失败,使用原始错误信息
|
||||
}
|
||||
}
|
||||
|
||||
$conn->send(json_encode([
|
||||
'type' => 'error',
|
||||
'code' => $errorCode,
|
||||
'error_type' => $errorType,
|
||||
'message' => '文件预览失败:' . $errorMessage
|
||||
]));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 封装文件预览的curl请求方法
|
||||
* @param string $url 请求URL
|
||||
* @param array $headers 请求头
|
||||
* @return string 响应内容
|
||||
*/
|
||||
private function curlGetFile($url, $headers = [])
|
||||
{
|
||||
$ch = curl_init();
|
||||
|
||||
// 设置URL
|
||||
curl_setopt($ch, CURLOPT_URL, $url);
|
||||
|
||||
// 设置请求方法
|
||||
curl_setopt($ch, CURLOPT_HTTPGET, true);
|
||||
|
||||
// 设置请求头
|
||||
if (!empty($headers)) {
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
|
||||
}
|
||||
|
||||
// 设置返回值
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
|
||||
curl_setopt($ch, CURLOPT_TIMEOUT, 60);
|
||||
|
||||
// 执行请求
|
||||
$response = curl_exec($ch);
|
||||
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||||
|
||||
// 关闭连接
|
||||
curl_close($ch);
|
||||
|
||||
if ($response === false) {
|
||||
throw new \Exception('Curl请求失败');
|
||||
}
|
||||
|
||||
if ($httpCode >= 400) {
|
||||
throw new \Exception('HTTP请求失败,状态码:' . $httpCode . ',响应:' . $response);
|
||||
}
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 封装文件上传的curl请求方法(适用于 Dify 1.9.0 版本)
|
||||
* @param string $url 请求URL
|
||||
@@ -696,7 +841,7 @@ class WebSocket extends WebSocketBase
|
||||
{
|
||||
try {
|
||||
// 记录开始处理流式请求
|
||||
$this->log('AI客服WebSocket流式请求开始处理,用户ID:' . $user_id . ',请求消息:' . $query, 'info');
|
||||
$this->log('AI客服WebSocket流式请求开始处理,用户ID:' . $user_id . ',请求内容:' . json_encode($requestData), 'info');
|
||||
|
||||
// 初始化模型
|
||||
$kefu_conversation_model = new KefuConversationModel();
|
||||
@@ -1316,9 +1461,10 @@ class WebSocket extends WebSocketBase
|
||||
* @param string $user_id 用户ID
|
||||
* @param string $conversation_id 会话ID
|
||||
* @param bool $stream 是否使用流式响应
|
||||
* @param array $origin_data 原始数据
|
||||
* @return array
|
||||
*/
|
||||
private function buildRequestData($message, $user_id, $conversation_id, $stream)
|
||||
private function buildRequestData($message, $user_id, $conversation_id, $stream, $origin_data)
|
||||
{
|
||||
$requestData = [
|
||||
'inputs' => [],
|
||||
@@ -1330,6 +1476,12 @@ class WebSocket extends WebSocketBase
|
||||
// 如果有会话ID,添加到请求中
|
||||
if (!empty($conversation_id)) {
|
||||
$requestData['conversation_id'] = $conversation_id;
|
||||
|
||||
// ----- 只有会话ID的情况下,下列情况才添加相关的数据
|
||||
// 如果有files字段,添加到请求中
|
||||
if (!empty($origin_data['files']) && count($origin_data['files']) > 0) {
|
||||
$requestData['files'] = $origin_data['files'];
|
||||
}
|
||||
}
|
||||
|
||||
return $requestData;
|
||||
|
||||
Reference in New Issue
Block a user