跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客GitHub 精选镜像工具UI配色美学隐私政策关于联系
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
PythonAI

Python 调用 Dify API 实现知识检索结果溯源展示

综述由AI生成演示了如何使用 Python 调用 Dify HTTP API 进行聊天问答及图文交互。核心流程包括上传文件获取 ID、发送消息(支持同步/流式)及会话管理。代码封装了 DifyChat 类,提供安全响应解析与多用户适配。重点展示了如何从 API 返回的 metadata 字段中提取知识检索资源信息(如 dataset_id、document_name、score 等),以便前端实现答案溯源展示。适用于快速验证 Dify 集成流程及构建 RAG 应用的前端展示逻辑。

星辰大海发布于 2026/4/6更新于 2026/5/2025 浏览
Python 调用 Dify API 实现知识检索结果溯源展示

一、Dify 聊天示例脚本说明

本脚本演示了如何通过 Dify HTTP API 进行聊天问答,并可选携带图片。核心流程:

  1. 上传文件(可选)
    • 调用 /v1/files/upload 上传本地图片,得到 upload_file_id。
    • 只有在需要图文问答时才上传;纯文本时可跳过。
  2. 发送对话消息
    • 调用 /v1/chat-messages,必填 query,可选传 files(当有 upload_file_id 时)。
    • response_mode = "blocking" 表示同步等待完整答案;如需流式可改为 "streaming" 并按 SSE 解析。
  3. 删除会话(可选)
    • 调用 DELETE /v1/conversations/{id};返回可能是 204 空 body,因此需要容错解析。

1.1、代码结构

  • DifyChat:极简封装,包含 upload_file、send、delete、create_chat(可选)。
  • _safe_parse_response:统一解析响应,优先尝试 JSON;否则返回状态码和文本,避免 JSONDecodeError。
  • 示例入口:根据 image_path 是否存在,选择纯文本或图文问答,并打印答案。

1.2、快速使用

  1. 配置:
    • api_url: 你的 Dify 服务地址(到 /v1)。
    • api_key: Dify 应用的 API Key(通常以 app- 开头)。
    • user: 请求用户标识,用于配额和会话归属。

可选删除会话:

if ret_send.get("conversation_id"):
    ret_delete = chat.delete(ret_send["conversation_id"])
    print(ret_delete)

图文问答:

ret_upload = chat.upload_file("xxx.jpg")
file_id = ret_upload["id"]
ret_send = chat.send("你的问题", file_id=file_id)
print(ret_send.get("answer"))

纯文本问答:

chat = DifyChat(api_url, api_key)
ret_send = chat.send("你的问题")
print(ret_send.get("answer"))

1.3、注意事项

  • files 字段仅在传入 file_id 时添加,允许无图时直接问答。
  • upload_file 使用 with open 避免句柄泄漏,并在 multipart 表单里传 user。
  • delete 可能返回 204/空 body,必须使用安全解析。
  • 示例里用 ret_send、ret_delete 避免变量覆盖导致拿不到 answer。
  • 若要流式输出,将 response_mode 改为 "streaming" 并按 SSE 处理返回。

1.4、适配其他项目的改动指引

  • 如需在多线程/多协程环境复用:将会话 id 存储在线程上下文或显式传入。
  • 若有多用户:实例化时传入不同 user 值;或在方法参数增加 user 覆盖。
  • 如需支持多文件:在 send 中把 data["files"] 扩展为文件列表,并按 Dify 要求传 type/transfer_method/upload_file_id。
  • 若要改为流式:封装一个 send_stream,使用 stream=True 并消费 SSE 事件。

二、代码部分

import os
import requests

class DifyChat:
    """
    一个极简的 Dify HTTP API 调用封装(适合快速验证流程)。
    你这里用到的核心接口:
    - POST /v1/chat-messages 发起一次对话消息(可选携带图片)
    - POST /v1/files/upload 上传文件,得到 upload_file_id(给 chat-messages 的 files 用)
    - DELETE /v1/conversations/{id} 删除会话(有的服务端会返回空 body)
    """
    def __init__(self, api_url, api_key, user="abc-123"):
        """
        :param api_url: Dify 服务地址(到 /v1 这一层),例如 http://10.0.100.98/v1
        :param api_key: Dify 应用 API Key(通常以 app- 开头)
        :param user: 用于标识请求用户的字符串。Dify 多数接口需要这个字段用于配额/会话归属。
        """
        self.api_url = api_url
        self.api_key = api_key
        self.user = user
        # JSON 请求通用 Header(upload_file 是 multipart,会单独传 headers)
        self.headers = {
            'Authorization': f'Bearer {self.api_key}',
            'Content-Type': 'application/json'
        }

    @staticmethod
    def _safe_parse_response(response):
        """
        尽量把响应解析成 JSON。
        - 像 DELETE 这类接口,经常返回 204 No Content(空 body)
        - 或者返回纯文本/HTML 错误页(不是 JSON)
        因此这里做'兜底',避免直接 response.json() 抛 JSONDecodeError。
        """
        try:
            # 204/205 等可能无 body
            if response.status_code in (204, 205) or not response.content:
                return {"status_code": response.status_code, "ok": response.ok, "text": ""}
            return response.json()
        except Exception:
            return {"status_code": response.status_code, "ok": response.ok, "text": response.text}

    def create_chat(self, chat_name):
        """ 创建 chat(是否需要取决于你的 Dify 应用/版本;很多情况下直接用 chat-messages 即可)。 """
        url = f'{self.api_url}/chats/create'
        data = {'chat_name': chat_name}
        response = requests.post(url, json=data, headers=self.headers)
        return self._safe_parse_response(response)

    def send(self, message, file_id=None, conversation_id=""):
        """
        发送一条消息(文本问答),可选带图片。
        :param message: 用户问题/提示词(query)
        :param file_id: upload_file 接口返回的 id(即 upload_file_id);不传则表示纯文本问答
        :param conversation_id: 继续同一个会话时传入;留空表示开启新会话
        """
        url = f'{self.api_url}/chat-messages'
        data = {
            # inputs: 给'工作流应用/带变量的应用'传入输入变量;纯聊天一般为空即可
            "inputs": {},
            # query: 你的提问文本
            "query": message,
            # blocking: 同步等待完整结果;如果你要流式输出,可改为 streaming(并按 SSE 解析)
            "response_mode": "blocking",
            # conversation_id: 传入就续聊,不传就新开一轮会话
            "conversation_id": conversation_id or "",
            # user: 用于标识请求用户
            "user": self.user
        }
        # 只有在传入 file_id 时才携带 files 字段(不传图就纯文本问答)
        # files 的含义:告诉 Dify'本次对话引用了哪些已上传文件'。
        if file_id:
            data["files"] = [{
                # type: 文件类型,这里是 image
                "type": "image",
                # transfer_method: local_file 表示使用'先上传 /files/upload,再在此引用 upload_file_id'的方式
                "transfer_method": "local_file",
                # upload_file_id: /files/upload 返回的 id
                "upload_file_id": file_id
            }]
        
        response = requests.post(url, json=data, headers=self.headers)
        return self._safe_parse_response(response)

    def delete(self, conver_id):
        """
        删除会话。
        注意:服务端可能返回 204(空响应体),所以不能直接 response.json()。
        """
        url = f'{self.api_url}/conversations/{conver_id}'
        data = {"user": self.user}
        response = requests.delete(url, json=data, headers=self.headers)
        return self._safe_parse_response(response)

    def upload_file(self, file_path):
        """
        上传本地文件到 Dify,返回值中通常包含:{"id": "..."}。
        随后把这个 id 作为 send(..., file_id=...) 的 upload_file_id 来引用。
        """
        url = f'{self.api_url}/files/upload'
        # Dify 通常要求 multipart form 里带 user 字段
        data = {"user": self.user}
        headers = {'Authorization': f'Bearer {self.api_key}'}
        with open(file_path, 'rb') as f:
            files = {'file': ("a.jpg", f, 'image/jpg')}
            response = requests.post(url, files=files, data=data, headers=headers)
        return self._safe_parse_response(response)

# 示例
if __name__ == "__main__":
    # 你的 Dify 服务地址(到 /v1)
    api_url = "http://127.0.0.1/v1"
    # 你的应用 API Key
    api_key = "app-xxxxxxxxxxxxxxxxxxxx"
    # 你的提问 query
    query = "时空之战的主要人物有哪些?"
    # image_path 为空字符串或不存在文件时:纯文本问答
    # image_path 指向真实图片文件时:会先上传图片,再在对话里引用该图片
    image_path = ""
    # image_path = "./beiguangdeshudianta1.jpg"
    
    chat = DifyChat(api_url, api_key)
    
    if not os.path.exists(image_path):
        # 方式 1:不上传图片,纯文本问答
        ret_send = chat.send(query)
    else:
        # 方式 2:需要图片时才上传,并把 file_id 带到 send 里
        ret_upload = chat.upload_file(image_path)
        file_id = ret_upload["id"]
        ret_send = chat.send(query, file_id=file_id)
    
    # send 的返回里一般会有 message_id / conversation_id / answer 等字段
    message_id = ret_send.get("message_id")
    conver_id = ret_send.get("conversation_id")
    print(ret_send)
    
    # 如果你的应用正常返回 answer,这里会打印答案
    if isinstance(ret_send, dict) and "answer" in ret_send:
        print(ret_send["answer"])
    
    # 可选:删除会话(有的场景你不需要删,保留会话便于续聊)
    # 注意:delete 的返回可能是 204 空 body,因此 ret_delete 不一定包含 JSON 字段
    if conver_id:
        ret_delete = chat.delete(conver_id)
        print(ret_delete)

三、ret 返回内容

ret_send 的返回全部内容,如下:

{
  "event": "message",
  "task_id": "e50a0154-5523-4c1a-93de-ae45a2568d00",
  "id": "c3f11257-cc16-4718-84f8-f5a550b38757",
  "message_id": "c3f11257-cc16-4718-84f8-f5a550b38757",
  "conversation_id": "3a1f9dd3-97a0-4d6e-bf74-bae87754ab02",
  "mode": "advanced-chat",
  "answer": "根据提供的知识内容,时空之战的主要人物包括:\n\n1. 大雄:故事的主角,原本性格懦弱、逃避责任,但在经历未来世界的战斗后实现内心成长。\n2. 哆啦 A 梦:大雄的好朋友,来自未来的机器猫,拥有众多神奇道具,是事件的关键推动者。\n3. 特兰克斯:来自未来的超级赛亚人,身披战甲,拥有强大战斗力,为拯救未来世界而寻求帮助。\n",
  "metadata": {
    "retriever_resources": [
      {
        "position": 1,
        "dataset_id": "04adf974-e176-4d80-8d56-9720718b2b37",
        "dataset_name": "时空之战_1",
        "document_id": "时空之战.md",
        "document_name": "时空之战.md",
        "data_source_type": null,
        "segment_id": null,
        "retriever_from": "workflow",
        "score": 0.36003251935408387,
        "hit_count": null,
        "word_count": null,
        "segment_position": null,
        "index_node_hash": null,
        "content": "# 哆啦 A 梦与超级赛亚人:时空之战\n\n在一个寻常的午后,大雄依旧坐在书桌前发呆,作业堆得像山,连第一页都没动。哆啦 A 梦在一旁翻着漫画,时不时叹口气,觉得这孩子还是一如既往的不靠谱。正当他们的生活照常进行时,一道强光突然从天而降,整个房间震动不已。光芒中走出一名金发少年,身披战甲、气势惊人,他就是来自未来的超级赛亚人——特兰克斯。他一出现便说出了惊人的话:未来的地球即将被黑暗势力摧毁,他来此是为了寻求哆啦 A 梦的帮助。\n\n哆啦 A 梦与大雄听后大惊,但也从特兰克斯坚定的眼神中读出了不容拒绝的决心。特兰克斯解释说,未来的敌人并非普通反派,而是一个名叫'黑暗赛亚人'的存在,他由邪恶科学家复制了贝吉塔的基因并加以改造,实力超乎想象。这个敌人不仅拥有赛亚人战斗力,还能操纵扭曲的时间能量,几乎无人可敌。特兰克斯已经独自战斗多年,但每一次都以惨败告终。他说:'科技,是我那个时代唯一缺失的武器,而你们,正好拥有它。'\n\n于是,哆啦 A 梦带着特兰克斯与大雄启动时光机,穿越到了那个即将崩溃的未来世界。眼前的景象令人震撼:城市沦为废墟,大地裂痕纵横,天空中浮动着压抑的黑雾。特兰克斯说,这正是黑暗赛亚人带来的结果,一切生命几乎都被抹杀,只剩他在苦苦支撑。大雄虽感到恐惧,但看到无辜的人类遭殃,内心逐渐燃起斗志。哆啦 A 梦则冷静地分析局势,决定使用他最强的三样秘密道具来对抗黑暗势力。\n\n三件秘密道具分别是:可以临时赋予超级战力的'复制斗篷',能暂停时间五秒的'时间停止手表',以及可在一分钟中完成一年修行的'精神与时光屋便携版'。大雄被推进精神屋内,在其中接受密集的训练,虽然只有几分钟现实时间,他却经历了整整一年的苦修。刚开始他依旧软弱,想放弃、想逃跑,但当他想起静香、父母,还有哆啦 A 梦那坚定的眼神时,他终于咬牙坚持了下来。出来之后,他的身体与精神都焕然一新,眼神中多了一份成熟与自信。\n\n最终战在黑暗赛亚人的空中要塞前爆发,特兰克斯率先出击,释放全力与敌人正面对决。哆啦 A 梦则用任意门和道具支援,从各个方向制造混乱,尽量压制敌人的时空能力。但黑暗赛亚人太过强大,仅凭特兰克斯一人根本无法压制,更别说击败。就在特兰克斯即将被击倒之际,大雄披上复制斗篷、冲破恐惧从高空跃下。他的拳头燃烧着金色光焰,目标直指敌人心脏。\n\n时间停止装置在关键时刻启动,世界陷入静止,大雄用这个短短五秒接近了敌人的盲点。他集中全力,一记重拳击穿了黑暗赛亚人的能量核心,引发巨大的能量反冲。黑暗赛亚人尖叫着化为碎光,天空中的黑雾瞬间散去,阳光重新洒落大地。特兰克斯倒在地上,看着眼前这个曾经懦弱的少年,露出了欣慰的笑容。他知道,这一次,是大雄救了世界。\n\n战后,未来世界开始恢复,植物重新生长,人类重建家园。特兰克斯告别时紧紧握住大雄的手,说:'你是我见过最特别的战士。'哆啦 A 梦也为大雄感到骄傲,说他终于真正成长了一次。三人站在山丘上,看着远方重新明亮的地平线,心中感受到从未有过的安宁。随后,哆啦 A 梦与大雄乘坐时光机返回了属于他们的那个年代,一切仿佛又恢复平静。\n\n回到现代后,大雄仿佛变了一个人,不再轻易抱怨、不再逃避责任。他认真写完作业,帮妈妈买菜,甚至主动练习体育,哆啦 A 梦惊讶得说不出话来。他知道,这不是一时兴起,而是大雄真正内心成长的结果。大雄有时会望着天空出神,仿佛还能看见未来世界的那一片废墟与重生的希望。他不会说出来,但他心中永远铭记那一战。\n\n几天后,电视新闻中突然出现一则画面:一位金发少年在街头击退了失控的机器人,引发市民围观与猜测。大雄放下手中的课本,望向哆啦 A 梦,两人心照不宣地笑了。也许,特兰克斯又回来了,也许,新的敌人正在逼近。冒险从未真正结束,而他们,早已准备好了。无论时空如何动荡,他们将永远并肩作战。\n",
        "page": null,
        "doc_metadata": null
      },
      {
        "position": 2,
        "dataset_id": "2030ad1d-3b1e-410a-8745-168a393a678f",
        "dataset_name": "博士论文知识库",
        "document_id": "配电网单相断线故障选线与定位方法的研究_张晓文.pdf",
        "document_name": "配电网单相断线故障选线与定位方法的研究_张晓文.pdf",
        "data_source_type": null,
        "segment_id": null,
        "retriever_from": "workflow",
        "score": 0.34555257968591596,
        "hit_count": null,
        "word_count": null,
        "segment_position": null,
        "index_node_hash": null,
        "content": "障定位方法,首先利用对称分量法,建立小电流接地系统单相断线接地复合故障的复合序网,分析不同故障类型零序电压的变化特征,根据零序电压幅值的差异区分单相断线电源侧接地故障和单相断线负荷侧接地故障。同时为了区分单相断线不接地故障与单相断线接地复合故障,按照躲过单相断线不接地时的最大零序电压对判据的启动值进行整定。该方法适用于中性点不接地系统或经消弧线圈接地的配电网,具有较高的可靠性。文献 [100] 利用序网络分析了单相断线故障发生后电源侧相电压、电流的特征,提出了基于相电流的故障区段定位方法,但是未考虑接地过渡电阻的大小。针对配电网谐振接地系统,文献 [101-103] 在建立的单相断线故障模型的基础上,分析了故障点上下游的相电压、线电压和中性点电压的变化,总结了谐振接地系统发生单相断线故障后各电压变化的规律,为谐振接地系统单相断线故障定位提供了理论依据。(3) 人工智能基于人工智能算法较多应用在配电网接地故障定位,在单相断线故障定位的应用较少。文献 [104] 基于配电网的多源数据提出了改进决策树的分支断线故障定位方法。该方法根据数据间的关联规则对数据进行分析,利用决策树计算出故障特征信息,并与关联规则进行匹配,确定故障位置。文献 [105] 同样也建立了兼具电气量、时空量特征的断线故障诊断特征库,通过最小冗余和最大相关算法筛选出主要特征,利用频繁模式增长算法挖掘出主要特征与结果特征之间的关联关系,进而确定故障区段。同样,文献 [106] 利用可视化来显示断线故障发生后电气量数据集的内部关系,然后使用关联规则挖掘找到与故障特征信息相关的因素,并将卡方作为相关性的度量,筛选出主要特征。根据各线路特征之间的关联关系,确定故障区段。该方法从多源数据中挖掘出有用的信息,具有较好的容错性,但是网络一旦发生变化,需要重新挖掘新的规则,使计算量变大。目前,大多数机器学习方法都是基于向量数据的,对于多维数据,必须将张量数据转换成向量数据。而多维数据向量化后,会破坏数据原有的结构信息,且还容易导致较高的计算量。另一方面,在解决实际问题时,由于各场景的数据千差万别,模型的配置没有统一的标准,很难最大程度发挥算法的优势。",
        "page": null,
        "doc_metadata": null
      },
      {
        "position": 3,
        "dataset_id": "2030ad1d-3b1e-410a-8745-168a393a678f",
        "dataset_name": "单相博士论文知识库",
        "document_id": "配电网单相断线故障选线与定位方法的研究_张晓文.pdf",
        "document_name": "配电网单相断线故障选线与定位方法的研究_张晓文.pdf",
        "data_source_type": null,
        "segment_id": null,
        "retriever_from": "workflow",
        "score": 0.1545743801846572,
        "hit_count": null,
        "word_count": null,
        "segment_position": null,
        "index_node_hash": null,
        "content": "第 3 章基于 Hausdorff 距离的单相断线故障选线方法在农村及偏远的乡镇,配电线路主要是以架空线路为主,受环境、外力等因素的影响,配电线路容易断开。断线故障一旦发生后,会引发大面积的连电事故,还可能会中断电能的传输。因此,本章针对架空线路提出了一种单相断线故障选线方法。上一章对中性点不接地系统发生单相断线故障及单相断线接地复合故障进行了分析发现:故障发生后,系统中故障线路的负序电流变化明显,可以用这个特征进行故障选线。但各线路的负序电流呈现出复杂的非线性特性和非平稳性,且采集的数据具有高维时序特性。另一方面,负序电流也并非只存在于断线故障,如果直接使用各馈线的负序电流进行故障选线,极易发生误判,因此,如何从负序电流信号中提取故障特征是故障选线的关键。传统的非线性分析方法在处理数据时具有局限性,如多尺度熵在粗粒化过程中,时间序列会随着尺度因子的增加而快速缩短,导致熵值的精度低,稳定性差,且忽略信号的实际幅值意味着信号的一些信息可能被丢失 [112,113]。为了解决上述问题,本章提出了基于精细时移多尺度标准差多样熵 (RTSMSDDE) 的负序电流特征提取方法。首先利用多样熵 (DE) 来描述故障信号的特征,DE 与现有的熵方法不同,它利用模式相似性的统计概率来描述状态分布,可以更好地反映内部模式的变化,并能够准确地估计信号的动态复杂性 [114]。其次针对 DE 在多尺度环境中的缺点,引入了时移多尺度方法代替传统粗粒化过程,并使用精细化方法来避免熵值在较大尺度因子下的波动。然后,综合考虑信号的实际幅值,将时间序列的多尺度标准差作为熵值的影响权重,有效地保存了原始数据的重要信息,避免了信息丢失。最后,结合 Hausdorff 距离算法衡量各馈线特征值的相似性,以实现故障选线,通过 MATLAB/Simulink 仿真验证了所提方法的有效性。",
        "page": null,
        "doc_metadata": null
      }
    ],
    "usage": {
      "prompt_tokens": 22886,
      "prompt_unit_price": "0",
      "prompt_price_unit": "0",
      "prompt_price": "0",
      "completion_tokens": 413,
      "completion_unit_price": "0",
      "completion_price_unit": "0",
      "completion_price": "0",
      "total_tokens": 23299,
      "total_price": "0",
      "currency": "USD",
      "latency": 4.649309985339642
    }
  },
  "created_at": 1769582803
}

其中 answer 是需要展示的内容,如下:

根据提供的知识内容,时空之战的主要人物包括: 1. 大雄:故事的主角,原本性格懦弱、逃避责任,但在经历未来世界的战斗后实现内心成长。 2. 哆啦 A 梦:大雄的好朋友,来自未来的机器猫,拥有众多神奇道具,是事件的关键推动者。 3. 特兰克斯:来自未来的超级赛亚人,身披战甲,拥有强大战斗力,为拯救未来世界而寻求帮助。

其中,知识检索的内容,存储在了 metadata 内,可用作前端对'知识检索'原文的追溯。

四、总结

本示例展示了调用 Dify 服务的完整流程及返回结构,便于前后端交互与结果展示。

目录

  1. 一、Dify 聊天示例脚本说明
  2. 1.1、代码结构
  3. 1.2、快速使用
  4. 1.3、注意事项
  5. 1.4、适配其他项目的改动指引
  6. 二、代码部分
  7. 示例
  8. 三、ret 返回内容
  9. 四、总结
  • 💰 8折买阿里云服务器限时8折了解详情
  • Magick API 一键接入全球大模型注册送1000万token查看
  • 🤖 一键搭建Deepseek满血版了解详情
  • 一键打造专属AI 智能体了解详情
极客日志微信公众号二维码

微信扫一扫,关注极客日志

微信公众号「极客日志V2」,在微信中扫描左侧二维码关注。展示文案:极客日志V2 zeeklog

更多推荐文章

查看全部
  • Python 调用 PubMed API 实战:构建医学文献搜索系统
  • 大模型数据标注员岗位深度解析:工作内容与行业现状
  • UI UX Pro Max:AI 辅助专业级 UI 设计工具
  • HarmonyOS6 RcInput 组件核心架构与类型系统设计
  • 在线 OJ 系统 Java Spring 竞赛管理功能实现
  • OpenTenBase 企业级分布式 HTAP 数据库部署指南
  • VSCode GitHub Copilot 插件模型加载失败排查指南
  • MultiResUNet 论文笔记:重新思考 U-Net 架构用于多模态生物医学图像分割
  • 海尔智能家居接入 HomeAssistant 指南
  • 队列的数组模拟与 STL queue 实战:从原理到代码实现
  • Obsidian 笔记与 Gitee 云存储同步方案
  • ChatGPT 插件生态爆发:自动写书流程与插件知识库构建方法
  • Claude Skills 实战指南:从安装到自动化开发
  • Linux 信号机制详解:从除零到 SIGPIPE
  • Python 标准库与第三方库实战:日期处理与 Excel 操作
  • 热门开源微服务框架与 Service Mesh 选型参考
  • 多旋翼无人机电源系统详解及常见故障分析
  • 扩散模型原理与图像生成实战
  • JiaJiaOCR:Java 开源 OCR 识别库
  • 基于 Web 的红色旅游网站的设计与实现

相关免费在线工具

  • RSA密钥对生成器

    生成新的随机RSA私钥和公钥pem证书。 在线工具,RSA密钥对生成器在线工具,online

  • Mermaid 预览与可视化编辑

    基于 Mermaid.js 实时预览流程图、时序图等图表,支持源码编辑与即时渲染。 在线工具,Mermaid 预览与可视化编辑在线工具,online

  • 随机西班牙地址生成器

    随机生成西班牙地址(支持马德里、加泰罗尼亚、安达卢西亚、瓦伦西亚筛选),支持数量快捷选择、显示全部与下载。 在线工具,随机西班牙地址生成器在线工具,online

  • curl 转代码

    解析常见 curl 参数并生成 fetch、axios、PHP curl 或 Python requests 示例代码。 在线工具,curl 转代码在线工具,online

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online