配置 IM 中的文件上传到阿里云OSS;更新 路由白名单
Build Docker / build (push) Canceled after 0s

This commit is contained in:
haomingming
2026-08-20 11:38:23 +08:00
parent e836e84421
commit 4ad8d5fa6f
4 changed files with 136 additions and 0 deletions
@@ -0,0 +1,88 @@
<?php
declare(strict_types=1);
namespace App\Amqp\Consumer;
use App\Model\MessageIm;
use Extend\Alibaba\Oss;
use GuzzleHttp\Client;
use Hyperf\Amqp\Annotation\Consumer;
use Hyperf\Amqp\Message\ConsumerMessage;
use Hyperf\Amqp\Result;
use PhpAmqpLib\Message\AMQPMessage;
use App\Utils\Log;
/**
* IM 多媒体文件异步处理消费者
*/
#[Consumer(exchange: 'amqp.direct', routingKey: 'UploadImMedia', queue: 'UploadImMediaQueue', name: "UploadImMediaConsumer", nums: 1)]
class UploadImMediaConsumer extends ConsumerMessage
{
public function consumeMessage($data, AMQPMessage $message): string
{
try {
$messageKey = $data['message_key'];
$msgType = $data['msg_type'];
$msgContent = $data['msg_content'];
// 初始化 Http Client 和 OSS
$client = new Client(['verify' => false, 'timeout' => 30]); // 设置合适的超时时间
$oss = new Oss();
$needUpdate = false;
$customDomain = config('alibaba.oss.custom_domain_name'); // 取 OSS 自定义域名
// 1. 根据不同类型提取 URL 并转存 OSS
if ($msgType === 'TIMImageElem' && isset($msgContent['ImageInfoArray'])) {
// 图片通常包含原图、大图、缩略图,根据需求替换
foreach ($msgContent['ImageInfoArray'] as &$imageInfo) {
if (!empty($imageInfo['URL'])) {
$content = $client->get($imageInfo['URL'])->getBody()->getContents();
$filename = "im/image/" . date('Ymd') . "/" . $messageKey . "_" . $imageInfo['Type'] . ".jpg";
$ossFilename = $oss->putObject($filename, $content);
$imageInfo['URL'] = rtrim($customDomain, '/') . '/' . $ossFilename;
$needUpdate = true;
}
}
} elseif ($msgType === 'TIMSoundElem' && !empty($msgContent['Url'])) {
// 语音消息
$content = $client->get($msgContent['Url'])->getBody()->getContents();
$filename = "im/sound/" . date('Ymd') . "/" . $messageKey . ".amr";
$ossFilename = $oss->putObject($filename, $content);
$msgContent['Url'] = rtrim($customDomain, '/') . '/' . $ossFilename;
$needUpdate = true;
} elseif ($msgType === 'TIMVideoFileElem') {
// 视频文件
if (!empty($msgContent['VideoUrl'])) {
$content = $client->get($msgContent['VideoUrl'])->getBody()->getContents();
$filename = "im/video/" . date('Ymd') . "/" . $messageKey . ".mp4";
$ossFilename = $oss->putObject($filename, $content);
$msgContent['VideoUrl'] = rtrim($customDomain, '/') . '/' . $ossFilename;
$needUpdate = true;
}
// 视频封面图
if (!empty($msgContent['ThumbUrl'])) {
$content = $client->get($msgContent['ThumbUrl'])->getBody()->getContents();
$filename = "im/video_thumb/" . date('Ymd') . "/" . $messageKey . ".jpg";
$ossFilename = $oss->putObject($filename, $content);
$msgContent['ThumbUrl'] = rtrim($customDomain, '/') . '/' . $ossFilename;
$needUpdate = true;
}
}
// 2. 更新对应记录的 JSON 数据
if ($needUpdate) {
MessageIm::where(['message_key' => $messageKey])->update([
'message_content' => json_encode($msgContent, JSON_UNESCAPED_UNICODE)
]);
}
return Result::ACK; // 任务成功完成
} catch (\Throwable $e) {
Log::getInstance("UploadImMediaConsumer")->error("IM多媒体上传OSS失败: " . $e->getMessage() . ' Line: ' . $e->getLine());
// 如果抛错可以 DROP 掉或者返回 REQUEUE 进入死信重试队列
return Result::DROP;
}
}
}
@@ -0,0 +1,27 @@
<?php
declare(strict_types=1);
namespace App\Amqp\Producer;
use Hyperf\Amqp\Annotation\Producer;
use Hyperf\Amqp\Message\ProducerMessage;
/**
* IM 多媒体文件异步下载并上传 OSS
*/
#[Producer(exchange: 'amqp.direct', routingKey: 'UploadImMedia')]
class UploadImMediaProducer extends ProducerMessage
{
/**
* @param array $data
* [
* "message_key" => "消息唯一ID",
* "msg_type" => "消息类型",
* "msg_content" => "消息具体内容(数组)"
* ]
*/
public function __construct(array $data)
{
$this->payload = $data;
}
}
+17
View File
@@ -1232,6 +1232,23 @@ class UserService extends BaseService
return $result;
}
// === 新增:投递上传OSS队列 ===
$mediaTypes = ['TIMImageElem', 'TIMSoundElem', 'TIMVideoFileElem', 'TIMFileElem'];
if (in_array($msg_data['MsgBody'][0]['MsgType'], $mediaTypes)) {
try {
$producer = \Hyperf\Context\ApplicationContext::getContainer()->get(\Hyperf\Amqp\Producer::class);
$producerMsg = new \App\Amqp\Producer\UploadImMediaProducer([
'message_key' => $msg_data['MsgKey'],
'msg_type' => $msg_data['MsgBody'][0]['MsgType'],
'msg_content' => $message_content,
]);
$producer->produce($producerMsg);
} catch (\Throwable $e) {
Log::getInstance("UserService-userImAfterSendMsg")->error("投递上传OSS队列失败: " . $e->getMessage());
}
}
// === 新增结束 ===
// im消息通知
if ($is_system == 0 && isset($message_send_result) && isset($order_inquiry_id)){
try {
+4
View File
@@ -19,6 +19,10 @@ class Auth
"/login/wechat_mobile_login" => "post", // 微信登陆
"/login/mobile_login" => "post", // 手机号登陆
"/code/phone" => "post",// 获取手机号验证码
"/patient/doctor/inquiry" => "get", // 获取问诊医生列表
"/doctor/info/inquiry/" => "get", // 获取医生详情-问诊
"/doctor/inquiry/service/" => "get", // 获取医生开启的服务列表
"/patient/doctor/evaluation/" => "get", // 获取医生评价
"/disease/expertise" => "get",// 疾病专长列表-搜索使用
"/area/province" => "get",// 获取省份信息
"/area/city" => "get", // 获取城市信息