目录

消息管理–发送和接收消息

更新时间:2022-02-28

本文介绍环信即时通讯 IM Web SDK 如何发送和接收多种类型的消息。

技术原理

环信即时通讯 IM Web SDK 支持发送和接收消息和已读回执,其中包含如下主要方法:

消息收发流程如下:

  1. 用户 A 发送一条消息到环信的消息服务器。
  2. 单聊时消息服务器发消息给用户 B,群聊时发消息给群内其他每个成员。
  3. 用户收到消息。

前提条件

开始前,请确保满足以下条件:

实现方法

构造消息

首先,构造一个消息。示例代码如下:

let msg = WebIM.message.create(option);  // 消息内容选项,下文详细介绍。

发送文本消息

示例如下:

// 单聊时发送文本消息。
function sendPrivateText() {
    let option = {
        chatType: 'singleChat',    // 会话类型,设置为单聊。
        type: 'txt',               // 消息类型。
        to: 'userID',              // 消息接收方(用户 ID)。
        msg: 'message content'     // 消息内容。
    }
    let msg = WebIM.message.create(option); 
    connection.send(msg).then(() => {
        console.log('send private text Success');  
    }).catch((e) => {
        console.log("Send private text error");  
    })
};

注意

群组消息和聊天室消息只需修改 option 对象下的其中 2 个参数:tochatType 群聊:to: (群组 ID)chatType:"groupChat" 聊天室:to: (聊天室 ID)chatType:"chatRoom"

接收消息

你可以通过 addEventHandler 注册监听器接收各类消息的回调,函数代码如下:

// handlerID 为用户自定义的 EventHandler ID, 可利用不同的 ID 注册多个监听器。
connection.addEventHandler('handlerID', {
    onConnected: function ( message ) {},      // 连接成功回调。
    onDisconnected: function ( message ) {},   // 连接关闭回调。
    onTextMessage: function ( message ) {},    // 收到文本消息。
    onEmojiMessage: function ( message ) {},   // 收到表情消息。
    onImageMessage: function ( message ) {},   // 收到图片消息。
    onCmdMessage: function ( message ) {},     // 收到命令消息。
    onAudioMessage: function ( message ) {},   // 收到音频消息。
    onLocationMessage: function ( message ) {},// 收到位置消息。
    onFileMessage: function ( message ) {},    // 收到文件消息。
    onCustomMessage: function ( message ) {},  // 收到自定义消息。
    onVideoMessage: function (message) {},     // 收到视频消息。
    onRecallMessage: function( message ){},    // 收到消息撤回回执。
    onReceivedMessage: function(message){},    // 收到消息送达服务器回执。
    onDeliveredMessage: function(message){},   // 收到消息送达客户端回执。
    onReadMessage: function(message){},        // 收到消息已读回执。
    onMutedMessage: function(message){},       // 如果用户在 A 群组被禁言,在 A 群发消息会触发该回调且消息不传递给该群的其它成员。
    onChannelMessage: function(message){}      // 收到会话已读回执,对方发送 `channel ack` 时会触发该回调。

    onPresence: function ( message ) {},       // 处理“广播”或“发布-订阅”消息,如联系人订阅请求、处理群组、聊天室被踢或解散等消息.
    onRoster: function ( message ) {},         // 处理好友申请。
    onInviteMessage: function ( message ) {},  // 处理群组邀请。
    onOnline: function () {},                  // 本机网络连接成功。
    onOffline: function () {},                 // 本机网络掉线。
    onError: function ( message ) {},          // 失败回调。
    onBlacklistUpdate: function (list) {       // 黑名单变动。
        // 查询黑名单、将好友拉黑以及将好友移出黑名单均会触发该回调,`list` 列明黑名单上的现有好友。
    },

});

撤回消息

消息撤回功能指用户可撤回特定时间内发出的消息,消息撤回时限默认 2 分钟。如需调整,可联系环信即时通讯 IM 的客户经理。

/**
 * 发送要撤回的消息。
 * @param {Object} option - 
 * @param {Object} option.mid -  要撤回消息的 ID。
 * @param {Object} option.to -   消息接收对象。
 * @param {Object} option.type - 消息类型:chat (单聊)、groupchat (群聊)和 chatroom (聊天室)。
   */
   let option = {
   mid: 'msgId',
   to: 'userID',
   chatType: 'singleChat'
   };
   connection.recallMessage(option).then((res) => {
   console.log('success', res)
   }).catch((error) => {
   // 消息撤回失败 (超过 2 分钟)。
   console.log('fail', error)
   })
   

监听要撤回的消息,示例如下:

WebIM.conn.addEventHandler('MESSAGES',{
   onRecallMessage: => (msg) {
       // 这里需要在本地删除对应的消息,也可以插入一条消息:“XXX撤回一条消息”。
   	   console.log('撤回成功',msg) 
   }, 
})
 

发送附件类型的消息

除文本消息外,还有几种其他类型的消息,其中语音、图片、短视频和文件等消息发送前先将附件上传到消息服务器。语音收到会自动下载,而图片和视频会自动下载缩略图。文件消息不会自动下载附件,接收方需调用下载附件的 API,具体实现参考下文。

发送附件消息,SDK 自动分两步完成:

  1. 上传附件到服务器,获得服务返回的附件信息等;
  2. 发送附件消息,消息体包含附件的基本信息和服务器路径等。

发送图片消息

示例如下:

function sendPrivateImg() {
    let input = document.getElementById('image');  // 选择要发送的图片。
    let file = WebIM.utils.getFileUrl(input);      // 将图片转换为 fileObj 格式。
    // 也可将文件自行处理成该格式。
    // let file = {
    //    data: file              file 对象。
    //    filename: 'fileName',   文件名称。
    //    filetype: 'filetype',   文件类型。
    // }
    let allowType = {
        'jpg': true,
        'gif': true,
        'png': true,
        'bmp': true
    };
    if (file.filetype.toLowerCase() in allowType) {
        let option = {
            chatType: 'singleChat',    // 会话类型,设置为单聊。
            type: 'img',               // 消息类型,设置为图片。
            to: 'userID',              // 消息接收方(用户 ID)。
            file: file,
            onFileUploadError: function () { 
                // 消息上传失败。     
                console.log('onFileUploadError');
            },
            onFileUploadProgress: function (progress) {  
                // 上传进度的回调。
                console.log(progress)
            },
            onFileUploadComplete: function () {  
                // 消息上传成功。 
                console.log('onFileUploadComplete');
            }
        };
        let msg = WebIM.message.create(option); 
        connection.send(msg).then(() => {
            console.log('Success');  // 消息发送成功。
        }).catch((e) => {
            console.log("Fail");     // 如禁言或拉黑后消息发送失败。
        });
    }
};

发送 URL 图片消息

示例如下:

需要在 WebIMConfig.js 中 设置 useOwnUploadFun: true

function sendPrivateUrlImg() {
    let option = {
        chatType: 'singleChat',    // 会话类型,设置为单聊。
        type: 'img',               // 消息类型,设置为图片。
        to: 'userID',              // 消息接收方(用户 ID)。
        url: 'imgUrl'              // 图片 URL。
    }
    let msg = WebIM.message.create(option); 
    connection.send(msg).then((res) => {
        console.log('success', res);  // 消息发送成功。
    }).catch((e) => {
        console.log("fail");          // 如禁言或拉黑后消息发送失败。
    });
 }

发送文件消息

示例如下:

function sendPrivateFile() {
    let input = document.getElementById('file');  // 选择要发送的文件。
    let file = WebIM.utils.getFileUrl(input);     // 将文件转换成 fileObj 格式。
    // 也可以将文件自行处理成该格式。
    // let file = {
    //    data: file              file 对象。
    //    filename: 'fileName',   文件名称。
    //    filetype: 'filetype',   文件类型。 
    // }
    let allowType = {
        'jpg': true,
        'gif': true,
        'png': true,
        'bmp': true,
        'zip': true,
        'txt': true,
        'doc': true,
        'pdf': true
    };
    if (file.filetype.toLowerCase() in allowType) {
        let option = {
            chatType: 'singleChat',    // 会话类型,设置为单聊。
            type: 'file',              // 消息类型,设置为文件。
            to: 'userID',              // 消息接收方(用户 ID)。
            file: file,
            filename: file.filename,
            onFileUploadError: function () { 
                // 消息上传失败。     
                console.log('onFileUploadError');
            },
            onFileUploadProgress: function (progress) {  
                // 上传进度的回调。
                console.log(progress)
            },
            onFileUploadComplete: function () {  
                // 消息上传成功。 
                console.log('onFileUploadComplete');
            }
        }
        let msg = WebIM.message.create(option); 
        connection.send(msg).then(() => {
            console.log('success');  // 消息发送成功。
        }).catch((e) => {
            console.log("fail");     // 如禁言或拉黑后消息发送失败。
        });
    }
};

发送音频消息

示例如下:

function sendPrivateAudio() {
    let input = document.getElementById('audio');  // 选择要发送的音频。
    let file = WebIM.utils.getFileUrl(input);      // 将音频转换为 fileObj 格式。
    let allowType = {
        'mp3': true,
        'amr': true,
        'wmv': true
    };
    if (file.filetype.toLowerCase() in allowType) {
        let option = {
            chatType: 'singleChat',             // 会话类型,设置为单聊。
            type: 'audio',                      // 消息类型,设置为音频。
            to: 'userID',                       // 消息接收方。
            file: file,
            filename: file.filename,
            onFileUploadError: function () {
                // 消息上传失败。      
                console.log('onFileUploadError');
            },
            onFileUploadProgress: function (e) {  
                // 上传进度的回调。
                console.log(e)
            },
            onFileUploadComplete: function () {   
                // 消息上传成功。
                console.log('onFileUploadComplete');
            }
        };
        let msg = WebIM.message.create(option); 
        connection.send(msg).then(() => {
            console.log('success');  // 消息发送成功。
        }).catch((e) => {
            console.log("fail");     // 如禁言或拉黑后消息发送失败。
        });;
    }
};

发送视频消息

示例如下:

function sendPrivateVideo() {
    let input = document.getElementById('video');  // 选择要发送的视频。
    let file = WebIM.utils.getFileUrl(input);      // 将文件转换为 fileObj 格式。
    let allowType = {
        'mp4': true,
        'wmv': true,
        'avi': true,
        'rmvb': true,
        'mkv': true
    };
    if (file.filetype.toLowerCase() in allowType) {
        let option = {
            chatType: 'singleChat',               // 会话类型,设置为单聊。
            type: 'video',                        // 消息类型,设置为视频。
            to: 'username',                       // 消息接收方。
            file: file,
            filename: file.filename,
            onFileUploadError: function () {
                // 消息上传失败。      
                console.log('onFileUploadError');
            },
            onFileUploadProgress: function (e) {  
                // 上传进度的回调。
                console.log(e)
            },
            onFileUploadComplete: function () {   
                // 消息上传成功。
                console.log('onFileUploadComplete');
            }
        };
        let msg = WebIM.message.create(option); 
        connection.send(msg).then(() => {
            console.log('Success');  // 消息发送成功。
        }).catch((e) => {
            console.log("Fail");     // 如禁言或拉黑后消息发送失败。
        });;
    }
};

发送贴图消息

利用以下代码可实现用户粘贴图片至输入框后发送:

document.addEventListener('paste', function (e) {
    if (e.clipboardData && e.clipboardData.types) {
        if (e.clipboardData.items.length > 0) {
            if (/^image\/\w+$/.test(e.clipboardData.items[0].type)) {
                let blob = e.clipboardData.items[0].getAsFile();
                let url = window.URL.createObjectURL(blob);
                let msg = new WebIM.message('img');  // 创建图片消息。
                let option = {
                    chatType: 'singleChat',    // 会话类型,设置为单聊。
                    type: 'img',               // 消息类型,设置为图片。
                    to: 'userID',              // 消息接收方(用户 ID)。
                    file: {data: blob, url: url},
                    onFileUploadError: function (error) {
                        console.log('error');
                    },
                    onFileUploadComplete: function (data) {
                        console.log('complete');
                    },
                }
                let msg = WebIM.message.create(option); 
                connection.send(msg);
            }
        }
    }
});

发送透传消息

透传消息可视为一条命令,通过发送这条命令给对方,通知对方要执行的操作,收到消息可以自定义处理。

透传消息适用于更新头像或昵称等场景。

let option = {
    chatType: 'singleChat',      // 会话类型,设置为单聊。      
    type: 'cmd',                 // 消息类型,设置为命令消息。
    to: 'userID',                // 消息接收方。
    action : 'action',           // 用户自定义操作。对于命令消息,该字段必填。
}

let msg = WebIM.message.create(option)

conn.send(msg).then(() => {
    console.log('success');  // 消息发送成功。
}).catch((e) => {
    console.log("fail");     // 如禁言获拉黑后消息发送会失败。
});

发送自定义消息

你可以在以上几种消息之外,自己定义消息类型,方便业务处理。自定义消息类型支持你自己设置一个消息的类型名称,这样你可以添加多种自定义消息。自定义消息的内容部分是 key,value 格式的,你需要自己添加并解析该内容。示例如下:

function sendCustomMsg() {
    let option = {
        chatType: 'singleChat',
        type: 'custom',
        to: 'userID',                        // 接收消息对象(用户 ID)   
        customEvent: 'customEvent',          // 自定义事件。
        customExts: {},                      // 消息内容,key/value 需要 string 类型。
        ext:{}                               // 消息扩展。
    }
    let msg = WebIM.message.create(option)
    connection.send(msg).then(() => {
        console.log('success');  // 消息发送成功。
    }).catch((e) => {
        console.log("fail");     // 如禁言或拉黑后消息发送失败。
    });
};

使用消息的扩展字段

当 SDK 提供的消息类型不满足需求时,你可以通过消息扩展字段来传递自定义的内容,从而生成自己需要的消息类型。

当目前消息类型不满足用户需求时,可以在扩展部分保存更多信息,例如消息中需要携带被回复的消息内容或者是图文消息等场景。

function sendPrivateText() {
    let option = {         
        chatType: 'singleChat', 
        type: 'txt',                  // 消息类型。
        msg: 'message content',                 
        to: 'userID',                 
        ext: {                        // 扩展字段。
            key: '自定义的value',
            key2: {
                key3: '自定义的value'
            }
        },       
    }
    let msg = WebIM.message.create(option)
    connection.send(msg).then(() => {
        console.log('success');  // 消息发送成功。
    }).catch((e) => {
        console.log("fail");     // 如禁言或拉黑后消息发送失败。
    });
};

注意

发送 ext 扩展消息,可以不带该字段。不过若有该字段,值不能是 “ext:null” 这种形式,否则会出错。

参考

消息相关限制: