当前位置: 首页 > news >正文

5.【SpringBoot3】文件上传

1. 文件上传到本地

需求分析

在用户更换头像或发布文章时,需要携带一个图片的 url 地址,该 url 地址是当用户访问文件上传接口,将图片上传成功后,服务器返回的地址。所以,后台需要提供一个文件上传接口,用来接收前端提交的文件数据,并且返回文件的访问地址。

在这里插入图片描述

接口文档

在这里插入图片描述

文件上传知识回忆

前端页面文件上传三要素:

  • 请求方式必须是 post;
  • 表单的编码类型必须是 multipart/form-data;
  • 文件表单项对应的类型必须是 file。

在这里插入图片描述

这三个要素满足后,用户就可以选择要上传的文件,点击提交按钮,最终把文件内容提交给服务器。当服务器接收到该请求后,如果服务器中的代码是使用 SpringMVC 框架编写的,我们就可以在方法上声明一个 MultipartFile 类型的参数,用来接收上传的文件内容。MultipartFile 提供了很多方法:

在这里插入图片描述
接口实现思路

Controller 中声明用于上传文件的 upload()方法,方法内部需要借助 MultipartFile 提供的 api,把文件内容写入本地磁盘文件,因此方法上要声明一个 MultipartFile 类型的参数。

在这里插入图片描述

现在还没有把文件内容上传到阿里云服务器,我们先把文件存储到服务器本地,保证接口访问是正常的,接口没问题后,再把文件上传到服务器测试。

@RestController
public class FileUploadController {@PostMapping("/upload")public Result<String> upload(MultipartFile file) throws IOException {//把文件内容存储到本地磁盘//获取文件原始的名称String originalFilename = file.getOriginalFilename();//file.transferTo的异常直接抛出去//再次存储的时候使用原来的文件名file.transferTo(new File("C:\\Users\\xxx\\Desktop\\files\\"+originalFilename));return Result.success("url访问地址...");}
}

postman 测试:

在这里插入图片描述

点击 select file 选择要上传的文件:

在这里插入图片描述

打开文件:

在这里插入图片描述

上传成功:

在这里插入图片描述

在这里插入图片描述

但是,现在的代码中还存在bug。当我们在 postman 中针对刚刚选择的图片再次点击 send 时,files 文件夹中并没有出现两张图片。原因是后上传的图片与之前上传的图片重名,导致之前的图片被覆盖了。在现实中,很有可能出现需要上传两张同名图片的需求,比如两个用户上传的图片同名。因此这个问题需要解决一下。

解决方式就是保证上传时的文件名唯一:在文件后缀名前面拼接UUID:

在这里插入图片描述

再次上传:

在这里插入图片描述

现在只是通过将文件上传到本地的方式模拟了将文件上传到服务器的过程。下面来介绍将文件上传到服务器的实现方式。

2. 文件上传到云服务器

云服务器会提供很多服务,当计算机连接上云服务器并开通某个服务后后就可以使用该服务了。

在这里插入图片描述

在本节,我们使用阿里云的对象存储服务。

使用云对象存储 OSS(Object Storage Service),可以通过网络随时存储和调用包括文本、图片、音频和视频等在内的各种文件。

使用第三方服务的通用思路

  • 准备工作:在服务提供商网站上注册用户,开通对应服务
  • 参照官方 SDK 编写入门程序:引入阿里云 OSS 相关的 jar 包,并参照提供的示例代码编写程序
  • 参照入门程序,将功能集成到自己的代码中使用

SDK:Software Development Kit
的缩写,软件开发工具包,包括辅助软件开发的依赖(jar包)、代码示例等,都可以叫做SDK。

2.1 准备工作

在服务提供商网站上注册用户,开通对应服务

在这里插入图片描述

① 登录之后,点击控制台

在这里插入图片描述

② 查看阿里云提供的所有服务

在这里插入图片描述
在这里插入图片描述

③ 搜索对象存储 OSS

在这里插入图片描述

④ 首次使用 OSS 需要开通
在这里插入图片描述
⑤ 按照提示开通后,开始创建 bucket

在这里插入图片描述

⑥ 填写必要信息,创建 bucket

在这里插入图片描述

⑦ 创建成功后,进入 bucket

在这里插入图片描述

⑧ 概览中展示了 bucket 基本信息和访问地址

在这里插入图片描述

⑨ 获取 AccessKey:

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

根据提示一步一步操作就能获取到 AccessKey。至此,准备工作完成。

2.2 参照官方 SDK 编写入门程序

导入阿里云 OSS 相关的依赖坐标,并参照提供的示例代码编写程序。

(1) 导入 OSS 相关依赖坐标

① 左侧点击概览:

在这里插入图片描述

② 滑动到底部,点击 SDK 下载

在这里插入图片描述

③ 找到 Java 版本,点击查看文档,会弹出帮助文档。点击“文档中心打开”

在这里插入图片描述

④ 点击”安装“

在这里插入图片描述

⑤ 将所需依赖坐标导入我们的 pom.xml 文件:

在这里插入图片描述

(2) 参照提供的示例代码编写程序

① 因为是要上传文件,所以点击:对象/文件➡上传文件➡简单上传

在这里插入图片描述

② 此处给出了一个示例代码,copy 一下

在这里插入图片描述

copy 的示例代码如下:

public class Demo {public static void main(String[] args) throws Exception {// Endpoint以华东1(杭州)为例,其它Region请按实际情况填写。String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";// 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();// 填写Bucket名称,例如examplebucket。String bucketName = "examplebucket";// 填写Object完整路径,完整路径中不能包含Bucket名称,例如exampledir/exampleobject.txt。String objectName = "exampledir/exampleobject.txt";// 创建OSSClient实例。OSS ossClient = new OSSClientBuilder().build(endpoint, credentialsProvider);try {// 填写字符串。String content = "Hello OSS,你好世界";// 创建PutObjectRequest对象。PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, objectName, new ByteArrayInputStream(content.getBytes()));// 如果需要上传时设置存储类型和访问权限,请参考以下示例代码。// ObjectMetadata metadata = new ObjectMetadata();// metadata.setHeader(OSSHeaders.OSS_STORAGE_CLASS, StorageClass.Standard.toString());// metadata.setObjectAcl(CannedAccessControlList.Private);// putObjectRequest.setMetadata(metadata);// 上传字符串。PutObjectResult result = ossClient.putObject(putObjectRequest);            } catch (OSSException oe) {System.out.println("Caught an OSSException, which means your request made it to OSS, "+ "but was rejected with an error response for some reason.");System.out.println("Error Message:" + oe.getErrorMessage());System.out.println("Error Code:" + oe.getErrorCode());System.out.println("Request ID:" + oe.getRequestId());System.out.println("Host ID:" + oe.getHostId());} catch (ClientException ce) {System.out.println("Caught an ClientException, which means the client encountered "+ "a serious internal problem while trying to communicate with OSS, "+ "such as not being able to access the network.");System.out.println("Error Message:" + ce.getMessage());} finally {if (ossClient != null) {ossClient.shutdown();}}}
}   

③ 修改示例代码

public class Demo {@Testpublic void test() throws Exception {// Endpoint:bucket概览中的访问端口->外网访问的地域节点String endpoint = "https://oss-cn-beijing.aliyuncs.com";// 阿里云为了防止AccessKeyId和AccessKeySecret泄露,建议以配置环境变量的方式来使用// 这里是测试代码,就不再配置环境变量了,直接定义两个变量来模拟,值都改成自己的String ACCESS_KEY_ID="**********";String ACCESS_KEY_SECRET="**********";// Bucket名称String bucketName = "big-event-bucket1";// 要存储的对象的名称,这里的对象可以是字符串、图片、视频等String objectName = "cat.jpg";// 创建OSSClient实例OSS ossClient = new OSSClientBuilder().build(endpoint, ACCESS_KEY_ID, ACCESS_KEY_SECRET);try {// 借助图片输入流对象构建出PutObjectRequest对象PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, objectName, new FileInputStream("C:\\Users\\xxx\\Desktop\\cat.jpg"));// 上传到服务器PutObjectResult result = ossClient.putObject(putObjectRequest);} catch (OSSException oe) {System.out.println("Caught an OSSException, which means your request made it to OSS, "+ "but was rejected with an error response for some reason.");System.out.println("Error Message:" + oe.getErrorMessage());System.out.println("Error Code:" + oe.getErrorCode());System.out.println("Request ID:" + oe.getRequestId());System.out.println("Host ID:" + oe.getHostId());} catch (ClientException ce) {System.out.println("Caught an ClientException, which means the client encountered "+ "a serious internal problem while trying to communicate with OSS, "+ "such as not being able to access the network.");System.out.println("Error Message:" + ce.getMessage());} finally {if (ossClient != null) {ossClient.shutdown();}}}
}

(3) 运行代码

上传成功:

在这里插入图片描述

点击图片名称,弹出图片具体信息。复制图片在服务器上的 url。

在这里插入图片描述

在浏览器中输入图片在服务器上的 url,搜索。此时已从服务器上下载了图片。

在这里插入图片描述

虽然上面相对于阿里云提供的示例代码该类很多,但只要完成这个 Demo 的改造,今后在一般情况下需要改的地方就只有下面两处:要存储的对象的名称、输入流中要存储的对象在本地的位置。

在这里插入图片描述

2.3 案例集成 OSS

参照入门程序,将功能集成到自己的代码中使用。

为了使用方便,需要把上面改造成功的代码封装成一个工具类。将来哪里需要使用,直接调用工具类的方法即可。

public class AliOssUtil {//这四个一般不变,所以抽取到成员处,声明为静态常量public static final String ENDPOINT = "https://oss-cn-beijing.aliyuncs.com";//区域节点public static final String ACCESS_KEY_ID="LTAI5t9NJbszDF431vYUkzbh";public static final String ACCESS_KEY_SECRET="d82arCTGqH3Turz4HY3NA4a9RufHn0";public static final String BUCKET_NAME = "big-event-bucket1";// Bucket名称// objectName: 要存储的对象的名称,这里的对象可以是字符串、图片、视频等// 方法内部可能发生变化的是objectName和输入流,因此以参数的方式暴露出去// 方法要返回图片在服务器上的访问地址,因此返回值是String类型public static String upLoadFile(String objectName, InputStream inputStream) throws Exception {// 创建OSSClient实例OSS ossClient = new OSSClientBuilder().build(ENDPOINT, ACCESS_KEY_ID, ACCESS_KEY_SECRET);String url = ""; //为了返回url,先声明一个空字符串try {PutObjectRequest putObjectRequest = new PutObjectRequest(BUCKET_NAME, objectName, inputStream);PutObjectResult result = ossClient.putObject(putObjectRequest);//上传到服务器//如果下面的代码不报错,就该给url赋值了//url组成:https://bucket名称.区域节点(去掉https://)/objectName//ENDPOINT.lastIndexOf("/")+1: 在ENDPOINT中,从最后一个"/"的下一个位置开始截取字符串url="https://"+BUCKET_NAME+"."+ENDPOINT.substring(ENDPOINT.lastIndexOf("/")+1)+"/"+objectName;} catch (OSSException oe) {System.out.println("Caught an OSSException, which means your request made it to OSS, "+ "but was rejected with an error response for some reason.");System.out.println("Error Message:" + oe.getErrorMessage());System.out.println("Error Code:" + oe.getErrorCode());System.out.println("Request ID:" + oe.getRequestId());System.out.println("Host ID:" + oe.getHostId());} catch (ClientException ce) {System.out.println("Caught an ClientException, which means the client encountered "+ "a serious internal problem while trying to communicate with OSS, "+ "such as not being able to access the network.");System.out.println("Error Message:" + ce.getMessage());} finally {if (ossClient != null) {ossClient.shutdown();}}return url;}
}

现在工具类准备好了,以后需要将文件上传阿里云只需调用 upLoadFile() 方法即可。

在 FileUploadController 中,之前我们将文件存储到了本地磁盘,现在不需要了,直接调用 upLoadFile() 方法将文件上传服务器。upLoadFile() 方法需要传递两个参数,filename 可以作为传入的第一个参数 objectName;第二个参数是文件输入流,MultipartFile 提供的 getInputStream() 方法可以提供该参数。最后将 upLoadFile() 方法返回的 url 响应给浏览器。

@RestController
public class FileUploadController {@PostMapping("/upload")public Result<String> upload(MultipartFile file) throws Exception {//把文件内容上传到阿里云服务器//获取原始文件名String originalFilename = file.getOriginalFilename();//使用UUID生成文件名,保证文件名唯一,从而防止文件被覆盖//originalFilename.lastIndexOf("."): 从文件名的最后一个"."处开始截取字符串(包括"."),即获取原始文件后缀名String filename = UUID.randomUUID().toString()+originalFilename.substring(originalFilename.lastIndexOf("."));// file.transferTo(new File("C:\\Users\\xxx\\Desktop\\files\\"+filename));//upLoadFile()方法上的异常直接抛出去即可String url = AliOssUtil.upLoadFile(filename, file.getInputStream());return Result.success(url);}
}

postman 测试:

在这里插入图片描述

在浏览器中输入文件访问地址,可以下载:

在这里插入图片描述

相关文章:

5.【SpringBoot3】文件上传

1. 文件上传到本地 需求分析 在用户更换头像或发布文章时&#xff0c;需要携带一个图片的 url 地址&#xff0c;该 url 地址是当用户访问文件上传接口&#xff0c;将图片上传成功后&#xff0c;服务器返回的地址。所以&#xff0c;后台需要提供一个文件上传接口&#xff0c;用…...

网络安全态势感知平台概述

网络安全态势感知平台 文章目录 网络安全态势感知平台网络安全态势感知平台是什么一、网络安全态势感知平台是什么&#xff1f;二、网络安全态势感知很重要三、网络安全态势感知基础功能以某公司态势平台产品为例具体功能有以下&#xff1a; 网络安全态势感知平台是什么 网络安…...

PHP导出csv文件格式(最快捷的方式导出Excel文件)

php导出csv文件格式比起用PHPExcel插件导出excel文件速度快100倍&#xff01; 以下是几种不同的PHP导出CSV文件的方法&#xff1a; 方法一&#xff08;php://output方式用fputcsv函数格式化成csv数据&#xff09;&#xff1a; ----------------------------------------------…...

vue3常用代码

文章目录 监听路由vue3 警告Feature flag __VUE_PROD_HYDRATION_MISMATCH_DETAILS__ is not explicitly defined.mitt、project/inject 无效解决方案 菜鸟做项目时发现很多 vue3 常用的代码&#xff0c;所以来总结一下&#xff01; 监听路由 import { useRoute } from "…...

【技术】SpringBoot 接口怎么加密解密

1. 介绍 在我们日常的Java开发中&#xff0c;免不了和其他系统的业务交互&#xff0c;或者微服务之间的接口调用 如果我们想保证数据传输的安全&#xff0c;对接口出参加密&#xff0c;入参解密。 但是不想写重复代码&#xff0c;我们可以提供一个通用starter&#xff0c;提…...

SqlAlchemy使用教程(六) -- ORM 表间关系的定义与CRUD操作

SqlAlchemy使用教程(一) 原理与环境搭建SqlAlchemy使用教程(二) 入门示例及编程步骤SqlAlchemy使用教程(三) CoreAPI访问与操作数据库详解SqlAlchemy使用教程(四) MetaData 与 SQL Express Language 的使用SqlAlchemy使用教程(五) ORM API 编程入门 本章内容&#xff0c;稍微有…...

嵌入式培训机构四个月实训课程笔记(完整版)-Linux ARM平台编程第五天-kernel配置(物联技术666)

链接&#xff1a;https://pan.baidu.com/s/1eb94AaDM-cIZsbr929Isbw?pwd1688 提取码&#xff1a;1688 上午&#xff1a;linux内核介绍 徐登伟老师 下午&#xff1a;linux的配置 教学内容&#xff1a; 一、基本kernel的制作&#xff1a; 1、去开源社区下载原…...

Java笔记(死锁、线程通信、单例模式)

一、死锁 1.概述 死锁 : 死锁是指两个或两个以上的进程在执行过程中&#xff0c;由于竞争资源或者由于彼此通信而造成的一种阻塞的现象&#xff0c;若无外力作用&#xff0c;它们都将无法往下执行。此时称系统处于死锁状态或系统产生了死锁&#xff0c;这些永远在互相等待的进…...

DAY11_(简易版)VUEElement综合案例

目录 1 VUE1.1 概述1.1.1 Vue js文件下载 1.2 快速入门1.3 Vue 指令1.3.1 v-bind & v-model 指令1.3.2 v-on 指令1.3.3 条件判断指令1.3.4 v-for 指令 1.4 生命周期1.5 案例1.5.1 需求1.5.2 查询所有功能1.5.3 添加功能 2 Element2.0 element-ui js和css和字体图标下载2.1 …...

【Kafka】开发实战和Springboot集成kafka

目录 消息的发送与接收生产者消费者 SpringBoot 集成kafka服务端参数配置 消息的发送与接收 生产者 生产者主要的对象有&#xff1a; KafkaProducer &#xff0c; ProducerRecord 。 其中 KafkaProducer 是用于发送消息的类&#xff0c; ProducerRecord 类用于封装Kafka的消息…...

【C语言】(1)初识C语言

什么是C语言 C语言是一种广泛应用的计算机编程语言&#xff0c;它具有强大的功能和灵活性&#xff0c;使其成为系统编程和底层开发的首选语言。C语言的设计简洁、高效&#xff0c;且不依赖于特定的硬件或系统&#xff0c;因此在各种计算平台上都能稳定运行。 C语言的特点 高…...

SpringCloudStream整合MQ(待完善)

概念 Spring Cloud Stream 的主要目标是各种各样MQ的学习成本&#xff0c;提供一致性的编程模型&#xff0c;使得开发者能够更容易地集成消息组件&#xff08;如 Apache Kafka、RabbitMQ、RocketMQ&#xff09; 官网地址&#xff1a;Spring Cloud Stream 组件 1. Binder 2…...

【Java 数据结构】包装类简单认识泛型

包装类&简单认识泛型 1 包装类1.1 基本数据类型和对应的包装类1.2 装箱和拆箱1.3 自动装箱和自动拆箱 2 什么是泛型3 引出泛型3.1 语法 4 泛型类的使用4.1 语法4.2 示例4.3 类型推导(Type Inference) 5 泛型如何编译的5.1 擦除机制5.2 为什么不能实例化泛型类型数组 6 泛型…...

第139期 做大还是做小-Oracle名称哪些事(20240125)

数据库管理139期 2024-01-25 第139期 做大还是做小-Oracle名称哪些事&#xff08;20240125&#xff09;1 问题2 排查3 扩展总结 第139期 做大还是做小-Oracle名称哪些事&#xff08;20240125&#xff09; 作者&#xff1a;胖头鱼的鱼缸&#xff08;尹海文&#xff09; Oracle A…...

驱动开发--多路复用-信号

一、多路复用 每个进程都有一个描述符数组&#xff0c;这个数组的下标为描述符&#xff0c; 描述符的分类&#xff1a; 文件描述符&#xff1a;设备文件、管道文件 socket描述符 1.1 应用层&#xff1a;三套接口select、poll、epoll select&#xff1a;位运算实现 监控的描…...

LeetCode 2859. 计算 K 置位下标对应元素的和【位操作】1000

本文属于「征服LeetCode」系列文章之一&#xff0c;这一系列正式开始于2021/08/12。由于LeetCode上部分题目有锁&#xff0c;本系列将至少持续到刷完所有无锁题之日为止&#xff1b;由于LeetCode还在不断地创建新题&#xff0c;本系列的终止日期可能是永远。在这一系列刷题文章…...

composer安装hyperf后,nginx配置hyperf

背景 引入hyperf项目用作微服务&#xff0c;使用composer 安装hyperf后&#xff0c;对hyperf进行nginx配置。 配置步骤 因为hyperf监听的是端口&#xff0c;不像其他laravel、lumen直接指向文件即可。所有要监听端口号。 1 配置nginx server {listen 80;//http&#xff1a…...

Flink对接Kafka的topic数据消费offset设置参数

scan.startup.mode 是 Flink 中用于设置消费 Kafka topic 数据的起始 offset 的配置参数之一。 scan.startup.mode 可以设置为以下几种模式&#xff1a; earliest-offset&#xff1a;从最早的 offset 开始消费数据。latest-offset&#xff1a;从最新的 offset 开始消费数据。…...

TryHackMe-Umbrella

靶场介绍 Breach Umbrella Corp’s time-tracking server by exploiting misconfigurations around containerisation. 利用集装箱化的错误配置&#xff0c;破坏Umbrella公司的时间跟踪服务器。 Task 1 What is the DB password? 数据库的密码是多少&#xff1f; 端口扫描&am…...

Excel导出警告:文件格式和拓展名不匹配

原因描述&#xff1a; Content-Type 原因&#xff1a;Content-Type&#xff0c;即内容类型&#xff0c;一般是指网页中存在的Content-Type&#xff0c;用于定义网络文件的类型和网页的编码&#xff0c;决定文件接收方将以什么形式、什么编码读取这个文件&#xff0c;这就是经常…...

谷歌浏览器插件

项目中有时候会用到插件 sync-cookie-extension1.0.0&#xff1a;开发环境同步测试 cookie 至 localhost&#xff0c;便于本地请求服务携带 cookie 参考地址&#xff1a;https://juejin.cn/post/7139354571712757767 里面有源码下载下来&#xff0c;加在到扩展即可使用FeHelp…...

React Native 开发环境搭建(全平台详解)

React Native 开发环境搭建&#xff08;全平台详解&#xff09; 在开始使用 React Native 开发移动应用之前&#xff0c;正确设置开发环境是至关重要的一步。本文将为你提供一份全面的指南&#xff0c;涵盖 macOS 和 Windows 平台的配置步骤&#xff0c;如何在 Android 和 iOS…...

【力扣数据库知识手册笔记】索引

索引 索引的优缺点 优点1. 通过创建唯一性索引&#xff0c;可以保证数据库表中每一行数据的唯一性。2. 可以加快数据的检索速度&#xff08;创建索引的主要原因&#xff09;。3. 可以加速表和表之间的连接&#xff0c;实现数据的参考完整性。4. 可以在查询过程中&#xff0c;…...

【SpringBoot】100、SpringBoot中使用自定义注解+AOP实现参数自动解密

在实际项目中,用户注册、登录、修改密码等操作,都涉及到参数传输安全问题。所以我们需要在前端对账户、密码等敏感信息加密传输,在后端接收到数据后能自动解密。 1、引入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId...

Linux相关概念和易错知识点(42)(TCP的连接管理、可靠性、面临复杂网络的处理)

目录 1.TCP的连接管理机制&#xff08;1&#xff09;三次握手①握手过程②对握手过程的理解 &#xff08;2&#xff09;四次挥手&#xff08;3&#xff09;握手和挥手的触发&#xff08;4&#xff09;状态切换①挥手过程中状态的切换②握手过程中状态的切换 2.TCP的可靠性&…...

【解密LSTM、GRU如何解决传统RNN梯度消失问题】

解密LSTM与GRU&#xff1a;如何让RNN变得更聪明&#xff1f; 在深度学习的世界里&#xff0c;循环神经网络&#xff08;RNN&#xff09;以其卓越的序列数据处理能力广泛应用于自然语言处理、时间序列预测等领域。然而&#xff0c;传统RNN存在的一个严重问题——梯度消失&#…...

Robots.txt 文件

什么是robots.txt&#xff1f; robots.txt 是一个位于网站根目录下的文本文件&#xff08;如&#xff1a;https://example.com/robots.txt&#xff09;&#xff0c;它用于指导网络爬虫&#xff08;如搜索引擎的蜘蛛程序&#xff09;如何抓取该网站的内容。这个文件遵循 Robots…...

【HarmonyOS 5 开发速记】如何获取用户信息(头像/昵称/手机号)

1.获取 authorizationCode&#xff1a; 2.利用 authorizationCode 获取 accessToken&#xff1a;文档中心 3.获取手机&#xff1a;文档中心 4.获取昵称头像&#xff1a;文档中心 首先创建 request 若要获取手机号&#xff0c;scope必填 phone&#xff0c;permissions 必填 …...

CMake控制VS2022项目文件分组

我们可以通过 CMake 控制源文件的组织结构,使它们在 VS 解决方案资源管理器中以“组”(Filter)的形式进行分类展示。 🎯 目标 通过 CMake 脚本将 .cpp、.h 等源文件分组显示在 Visual Studio 2022 的解决方案资源管理器中。 ✅ 支持的方法汇总(共4种) 方法描述是否推荐…...

A2A JS SDK 完整教程:快速入门指南

目录 什么是 A2A JS SDK?A2A JS 安装与设置A2A JS 核心概念创建你的第一个 A2A JS 代理A2A JS 服务端开发A2A JS 客户端使用A2A JS 高级特性A2A JS 最佳实践A2A JS 故障排除 什么是 A2A JS SDK? A2A JS SDK 是一个专为 JavaScript/TypeScript 开发者设计的强大库&#xff…...