你还在使用付费图床?一文实现钉钉发送图片自由
评论
收藏

你还在使用付费图床?一文实现钉钉发送图片自由

经验分享
莫奈
2025-05-16 21:07·浏览量:6202
莫奈
发布于 2024-04-17 17:07更新于 2025-05-16 21:076202浏览

经常使用钉钉的朋友应该不会陌生,利用钉钉机器人来进行消息的分发是再熟悉不过的了,那么就像大家熟知的一样,单单文本并不能满足我们的日常使用,同时图片的信息量也是我们文本无法比拟的,那么这时候就会蹦出一个老问题了,如何使用钉钉机器人发图片,首先你有自己的图床吧?

因为目前钉钉自定义机器人使用markdown发送图片时,不支持使用base64编码的方式,只支持使用网络路径的方式,如果你使用base64编码的方式,钉钉会将其原样输出,而不会转换成图片,所以你使用markdown发送图片时,需要使用网络图片,无法本地发送的本地文件。所以你搭建一个服务器做为图床,或者白嫖免费的图床,显然一个贵,一个不安全,那么如何两全其美呢?

今天给大家带来的是,钉钉发送图片”无图床“版本的解决方案,确切说是不止图片,刚好最近是客户提出了一个问题,使用目前指令的钉盘发送图片,钉钉有时候会显示出预览,有时又不会,所以造成了需要再点一次预览才行的情况,于是乎,去网络翻垃圾找到了对应的接口,尝试再尝试之后产生如下解决方案


1.效果展示

图片发送演示偷笑

开心图片发送自由后,这次我们还可以实现音频、视频、文件的发送

2.实现原理

既然展示完了,那我们来聊一聊指令的实现原理吧,这次能够实现各类文件的发送,主要是依托于钉钉的媒体文件,那么什么是媒体文件呢

答:媒体文件是钉钉提供的开放能力之一,可以在企业内部应用和第三方企业应用内的文件储存场景使用,而且媒体文件使用的空间是钉钉提供给钉钉组织的特定存储空间,不属于钉钉组织的钉盘空间,上传媒体文件,不占用钉钉组织的钉盘空间

!!需要注意的是虽然本功能媒体文件使用的空间没有大小限制,但是是有次数要求限制,每个钉钉组织每年可执行上传的次数上限为1万次

3.如何实现媒体文件上传和发送

1)创建一个企业内部应用,然后给应用开通机器人的能力

2)复制应用的Client ID 和 Client Secret,以及RobotCode

3)获取应用访问凭证accessToken,上传媒体文件

这一块就是我们熟悉的发请求环节啦,详细内容见钉钉开放平台:

https://open.dingtalk.com/document/orgapp/upload-media-files

4)我们请求成功后,就可以获取到我们的媒体文件id了,使用它结合机器人发送群聊消息请求,就可以完成我们前面演示的效果啦

4.注意事项以及使用

--注意事项:

1)使用钉钉的媒体文件,会有一部分文件类型和大小的限制,这里我们需要注意一下,具体如下:

      • image:图片,图片最大20MB。支持上传jpg、gif、png、bmp格式
      • voice:语音,语音文件最大2MB。支持上传amr、mp3、wav格式
      • video:视频,视频最大20MB。支持上传mp4格式
      • file:普通文件,最大20MB。支持上传doc、docx、xls、xlsx、ppt、pptx、zip、pdf、rar格式

2)使用钉钉机器人发群聊消息时,如果发送的是视频媒体,需要给一个视频封面,也就是我们需要一个图片的媒体id做为视频媒体的封面图

3)虽然会有一些大小的限制,但是足够支持我们自由发送图片,对于视频,音频或者文件超出了范围怎么办?这里推荐一下驿站老师封装的【钉钉云盘操作】,使用该指令就可以利用钉盘完成超出范围的大文件群聊消息发送啦

--使用:

我这边已经封装好了一个指令,有需要的企业用户可以找自己的技术支持要一下进行体验使用~

1)AppKey、AppSecret、RobotCode对应刚才保存的Client ID, Client Secret和RobotCode

2)群会话ID是我们机器人位于群聊的id,获取方式参考驿站老师封装的云盘文档中的群会话ID获取步骤

https://ydrpa.yuque.com/org-wiki-ydrpa-xtutvv/ga4dm6/gmubbci9u26qdf2x

不过需要注意一下,这里指令使用的群会话id是另一个,获取方法还是链接里面的,不过我们得到的会是这样的结果:

我们需要的是"openConversationId"填写到群会话id

3)文件类型根据需要选择,支持文件、图片、音频以及视频

4)上传视频文件的时候,需要一个图片做为视频的封面哦,不然会报错的


最后是我的源码分享环节,有能力的伙伴可以自行封装一下,如果这次的分享有帮到你,还请在评论区一键三连一下谢谢,你的支持将会是我的动力,如果大家遇到什么问题,也欢迎大家在评论区互动

import json
import requests
import os

REQUEST_HEAD_DD = "https://api.dingtalk.com/v1.0"
REQUEST_OLDHEAD_DD = "https://oapi.dingtalk.com/"

IMAGE_TYPE = ["jpg", "gif", "png", "bmp"]
VOICE_TYPE = ["amr", "mp3", "wav"]
VIDEO_TYPE = ["mp4"]
FILE_TYPE = ["doc", "docx", "xls", "xlsx", "ppt", "pptx", "zip", "pdf", "rar"]

class FileError(Exception):
    def __init__(self, ErrorInfo):
        super().__init__(self)
        self.errorinfo = ErrorInfo

    def __str__(self):
        return self.errorinfo

class DD:
    def __init__(self, robotKey, robotSecret, typeChoose, filePath):
        self.robotKey = robotKey
        self.robotSecret = robotSecret
        self.typeChoose = typeChoose
        self.filePath = filePath

    def token(self):
        try:
            url = REQUEST_HEAD_DD + "/oauth2/accessToken"
            headers = {"Content-Type": "application/json"}
            body = {"appKey": self.robotKey, "appSecret": self.robotSecret}
            token_Get = requests.post(url=url, headers=headers, json=body)
            self.token_text = token_Get.json()['accessToken']
            return 1
        except Exception as e:
            print("get token Error: " + str(e))

    def media(self):
        self.fileCheck()
        self.token()
        self.typeCheck()
        url = REQUEST_OLDHEAD_DD + "media/upload"
        payload = {'type': self.typeChoose}
        files = {('media', (self.filename, open(self.filePath, 'rb'), self.suffix))}
        params = {"access_token": self.token_text}
        try:
            respondResult = requests.post(url=url, data=payload, files=files, params=params)
            media_id = respondResult.json()['media_id']
            return media_id
        except Exception as E:
            print("Error Get mediaID")

    def typeCheck(self):
        (temp, filename) = os.path.split(self.filePath)
        (name, suffix) = os.path.splitext(filename)
        suffix = suffix.replace(".", "")
        if self.typeChoose == "image":
            if suffix in IMAGE_TYPE:
                self.filename = filename
                self.suffix = suffix
            else:
                raise FileError("Error Unsupported type \"" + suffix + "\"")
        elif self.typeChoose == "voice":
            if suffix in VOICE_TYPE:
                self.filename = filename
                self.suffix = suffix
            else:
                raise FileError("Error Unsupported type \"" + suffix + "\"")
        elif self.typeChoose == "video":
            if suffix in VIDEO_TYPE:
                self.filename = filename
                self.suffix = suffix
            else:
                raise FileError("Error Unsupported type \"" + suffix + "\"")
        elif self.typeChoose == "file":
            if suffix in FILE_TYPE:
                self.filename = filename
                self.suffix = suffix
            else:
                raise FileError("Error Unsupported type \"" + suffix + "\"")

    def fileCheck(self):
        if os.path.exists(self.filePath) is False:
            raise FileError("Error Please Check FilePath")

    def sendMessage(self, robotCode, chatid, mediaId, videoPicMediaId):
        url = REQUEST_HEAD_DD + "/robot/groupMessages/send"
        headers = {"Content-Type": "application/json", "x-acs-dingtalk-access-token": self.token_text}
        body = {"robotCode": robotCode, "openConversationId": chatid}
        if self.typeChoose == "image":
            body["msgKey"] = "sampleMarkdown"
            body["msgParam"] = "{\"text\":\"![pic](" + mediaId + ")\"}"
        elif self.typeChoose == "voice":
            body["msgKey"] = "sampleAudio"
            body["msgParam"] = json.dumps({"duration": "9999", "mediaId": mediaId})
        elif self.typeChoose == "video":
            body["msgKey"] = "sampleVideo"
            body["msgParam"] = json.dumps({"duration": "9999",
                                           "videoMediaId": mediaId,
                                           "videoType": self.suffix,
                                           "picMediaId": videoPicMediaId,
                                           "height": "160",
                                           "width": "90"
                                           })
        elif self.typeChoose == "file":
            body["msgKey"] = "sampleFile"
            body["msgParam"] = json.dumps({"mediaId": mediaId,
                                           "fileName": self.filename,
                                           "fileType": self.suffix})
        body = json.dumps(body, indent=2, sort_keys=True)
        try:
            respond = requests.post(url=url, headers=headers, data=body)
        except Exception as E:
            print("send Error")

def send_picture(ddkey, ddSecret, Path, robotCode, chatid):
    dd = DD(ddkey, ddSecret, "image", Path)
    dd.sendMessage(robotCode, chatid, dd.media(), "")

def send_voice(ddkey, ddSecret, Path, robotCode, chatid):
    dd = DD(ddkey, ddSecret, "voice", Path)
    dd.sendMessage(robotCode, chatid, dd.media(), "")

def send_video(ddkey, ddSecret, videoPath, robotCode, chatid, picPath):
    dd = DD(ddkey, ddSecret, "video", videoPath)
    videoMedia = dd.media()
    dd.filePath = picPath
    dd.typeChoose = "image"
    picMedia = dd.media()
    dd.typeChoose = "video"
    dd.sendMessage(robotCode, chatid, videoMedia, picMedia)

def send_file(ddkey, ddSecret, Path, robotCode, chatid):
    dd = DD(ddkey, ddSecret, "file", Path)
    dd.sendMessage(robotCode, chatid, dd.media(), "")

def robot_send(ddkey, ddSecret, robotCode, chatid, Path, type, videoPicPath):
    if type == "图片":
        send_picture(ddkey, ddSecret, Path, robotCode, chatid)
    elif type == "音频":
        send_voice(ddkey, ddSecret, Path, robotCode, chatid)
    elif type == "视频":
        if videoPicPath == "":
            raise FileError("please give video pic")
        send_video(ddkey, ddSecret, Path, robotCode, chatid, videoPicPath)
    elif type == "文件":
        send_file(ddkey, ddSecret, Path, robotCode, chatid)
       
//拿走使用的话,悄悄在评论区吱一声~
//author:monai 4/17



收藏27
全部评论1
最新
发布评论
评论