OSS-服务端签名Web端直传+STS获取临时凭证+POST签名v4版本开发过程中的细节

这里写自定义目录标题

  • 配置OSS
  • 服务端代码
    • 初始化STS Client
    • 获取STS临时凭证
    • 创建policy计算SigningKey
      • OSSUtil.java
      • STSPolicyDTO.java
    • 提供接口
  • Apifox模拟Web端文件直传

本文主要结合服务端STS获取临时凭证(签名)直传官方文档对开发中比较容易出错的地方加以提醒;建议主要还是以官方文档为主。本文中的代码几乎就是官方给的代码示例。
阅读前请先比对OSS版本,这可能关系到本文中列举的坑是否能解决你的问题

		<dependency><groupId>com.aliyun.oss</groupId><artifactId>aliyun-sdk-oss</artifactId><version>3.17.4</version></dependency><dependency><groupId>com.aliyun</groupId><artifactId>sts20150401</artifactId><version>1.1.6</version></dependency>

只不过重要的OSS基本参数官方建议给到环境变量中;本文直接将重要的OSS基础信息给到了Spring主配置文件中(方便后期迁移到Nacos的配置中心管理),知道了这一点,在接下来代码阅读的过程中看到如下的代码片段也就不陌生了。
在这里插入图片描述
接下来也将OSS基本参数封装成AliOSSProp的代码顺手贴出来

/*** oss的基础信息* prefix = "alibaba.oss"表示Spring、Springboot主配置文件中以alibaba.oss打头的自定义参数值,都将一 一映射到当前类的属性上*/
@ConfigurationProperties(prefix = "alibaba.oss")
@Component
@Getter
@Setter
public class AliOSSProp {private String accessKeyId;private String secretAccessKey;/*** 确保获取临时访问凭证时Endpoint使用STS域名,例如String endpoint = "sts.cn-hangzhou.aliyuncs.com"。* 更多信息,请参见步骤五:获取临时访问凭证。* https://help.aliyun.com/document_detail/100624.html?spm=api-workbench.Troubleshoot.0.0.5ba77185ILElOT#section-5xa-zdn-s0q*/private String endpoint;private String bucket;/*** RAM 访问控制/身份管理/角色/ARN属性值*/private String roleArn;private String region;
}

在这里插入图片描述

配置OSS

这个在官方文档中有很详细的教程,不多赘述

服务端代码

服务端最主要的事情:使用STS生成一个临时的凭证给客户端使用;客户端拿到该临时凭证就可以直接将文件上传至OSS

初始化STS Client

这里有个点需要注意:endpoint 需要添加sts.前缀,
考虑到STS Client只需要初始化一次,所以将其注册为一个Bean


@Beanpublic com.aliyun.sts20150401.Client ossStsClient() throws Exception {// 工程代码泄露可能会导致 AccessKey 泄露,并威胁账号下所有资源的安全性。以下代码示例仅供参考。com.aliyun.teaopenapi.models.Config config = new com.aliyun.teaopenapi.models.Config()// 必填,请确保代码运行环境设置了环境变量 OSS_ACCESS_KEY_ID。.setAccessKeyId(aliOSSProp.getAccessKeyId())// 必填,请确保代码运行环境设置了环境变量 OSS_ACCESS_KEY_SECRET。.setAccessKeySecret(aliOSSProp.getSecretAccessKey());// Endpoint 请参考 https://api.aliyun.com/product/Sts// 确保获取临时访问凭证时Endpoint使用STS域名config.endpoint = "sts."+aliOSSProp.getEndpoint();return new com.aliyun.sts20150401.Client(config);}

获取STS临时凭证

这部分没有什么需要注意的点,可以完全照搬

import com.aliyun.sts20150401.models.AssumeRoleResponseBody;
import com.aliyun.oss.OSSException;/*** 获取STS临时凭证* @return AssumeRoleResponseBodyCredentials 对象*/private AssumeRoleResponseBody.AssumeRoleResponseBodyCredentials getCredential(){com.aliyun.sts20150401.models.AssumeRoleRequest assumeRoleRequest = new com.aliyun.sts20150401.models.AssumeRoleRequest()// 必填,请确保代码运行环境设置了环境变量 OSS_STS_ROLE_ARN.setRoleArn(aliOSSProp.getRoleArn()).setRoleSessionName("idooyRoleSessionName");// 自定义会话名称com.aliyun.teautil.models.RuntimeOptions runtime = new com.aliyun.teautil.models.RuntimeOptions();try {// 复制代码运行请自行打印 API 的返回值com.aliyun.sts20150401.models.AssumeRoleResponse response = ossStsClient.assumeRoleWithOptions(assumeRoleRequest, runtime);// credentials里包含了后续要用到的AccessKeyId、AccessKeySecret和SecurityToken。return response.body.credentials;} catch (TeaException error) {// 此处仅做打印展示,请谨慎对待异常处理,在工程项目中切勿直接忽略异常。// log.error("STS方式获取临时凭证失败原因===》{}",error.getMessage());throw new OSSException("STS方式获取临时凭证失败原因===》"+error.getMessage());} catch (Exception e) {throw new OSSException(e.getMessage());}}

创建policy计算SigningKey

这部分的代码很长,但是注释很清晰;当然也不需要完全搞懂,照搬就好。

  • 这部分代码中的魔法值(String字面量)要小心,别无意间给修改或者给粘错了
  • 这部分使用了三种日期格式,分别是:“yyyyMMdd’T’HHmmss’Z’”、“yyyyMMdd”、“yyyy-MM-dd’T’HH:mm:ss.SSS’Z’”。注意区分
  • uploadDir 变量值请自定义修改
  • 官方直接将结果塞进了map中,本文将其封装为了一个DTO对象
@Resourceprivate com.aliyun.sts20150401.Client ossStsClient;/***     指定过期时间,单位为秒。*/private static final Long EXPIRE_TIME = 3600L;private static final String TIME_FORMAT_PATTERN_1 = "yyyyMMdd'T'HHmmss'Z'";/*** 定义日期时间格式*/private static final String TIME_FORMAT_PATTERN_2 = "yyyyMMdd";@ResourceAliOSSProp aliOSSProp;/*** 还是“服务端验签web端直传的方式”只不过采用了更加安全的STS方式* @return*/@Overridepublic STSPolicyDTO getSTSUploadPolicy() throws JsonProcessingException {String host = "https://" + aliOSSProp.getBucket() + "." + aliOSSProp.getEndpoint();// 设置上传到OSS文件的前缀,可置空此项。置空后,文件将上传至Bucket的根目录下;每一天产生一个文件夹// brand/是自定义目录String uploadDir = "brand/"+LocalDate.now();String region = aliOSSProp.getRegion();// 临时的凭证信息AssumeRoleResponseBody.AssumeRoleResponseBodyCredentials credential = getCredential();String accessKeyId =  credential.getAccessKeyId();String accessKeySecret =  credential.getAccessKeySecret();String securityToken =  credential.getSecurityToken();//获取x-oss-credential里的date,当前日期,格式为yyyyMMddZonedDateTime today = ZonedDateTime.now().withZoneSameInstant(ZoneOffset.UTC);DateTimeFormatter formatter = DateTimeFormatter.ofPattern(TIME_FORMAT_PATTERN_2);String date = today.format(formatter);//获取x-oss-dateZonedDateTime now = ZonedDateTime.now().withZoneSameInstant(ZoneOffset.UTC);DateTimeFormatter formatter2 = DateTimeFormatter.ofPattern(TIME_FORMAT_PATTERN_1);String x_oss_date = now.format(formatter2);// 步骤1:创建policy。String x_oss_credential = accessKeyId + "/" + date + "/" + region + "/oss/aliyun_v4_request";ObjectMapper mapper = new ObjectMapper();Map<String, Object> policy = new HashMap<>();policy.put("expiration", OSSUtil.generateExpiration(EXPIRE_TIME));List<Object> conditions = new ArrayList<>();Map<String, String> bucketCondition = new HashMap<>();bucketCondition.put("bucket", aliOSSProp.getBucket());conditions.add(bucketCondition);Map<String, String> securityTokenCondition = new HashMap<>();securityTokenCondition.put("x-oss-security-token", securityToken);conditions.add(securityTokenCondition);Map<String, String> signatureVersionCondition = new HashMap<>();signatureVersionCondition.put("x-oss-signature-version", "OSS4-HMAC-SHA256");conditions.add(signatureVersionCondition);Map<String, String> credentialCondition = new HashMap<>();credentialCondition.put("x-oss-credential", x_oss_credential); // 替换为实际的 access key idconditions.add(credentialCondition);Map<String, String> dateCondition = new HashMap<>();dateCondition.put("x-oss-date", x_oss_date);conditions.add(dateCondition);conditions.add(Arrays.asList("content-length-range", 1, 10240000));conditions.add(Arrays.asList("eq", "$success_action_status", "200"));conditions.add(Arrays.asList("starts-with", "$key", uploadDir));policy.put("conditions", conditions);String jsonPolicy = mapper.writeValueAsString(policy);// 步骤2:构造待签名字符串(StringToSign)。// String stringToSign = new String(Base64.encodeBase64(jsonPolicy.getBytes()));String stringToSign = cn.hutool.core.codec.Base64.encode(jsonPolicy.getBytes());// System.out.println("stringToSign: " + stringToSign);// 步骤3:计算SigningKey。byte[] dateKey = OSSUtil.getHmacSHA256(("aliyun_v4" + accessKeySecret).getBytes(), date);byte[] dateRegionKey = OSSUtil.getHmacSHA256(dateKey, region);byte[] dateRegionServiceKey = OSSUtil.getHmacSHA256(dateRegionKey, "oss");byte[] signingKey = OSSUtil.getHmacSHA256(dateRegionServiceKey, "aliyun_v4_request");// System.out.println("signingKey: " + BinaryUtil.toBase64String(signingKey));// 步骤4:计算Signature。byte[] result = OSSUtil.getHmacSHA256(signingKey, stringToSign);String signature = BinaryUtil.toHex(result);return new STSPolicyDTO().setPolicy(stringToSign).setX_oss_credential(x_oss_credential).setX_oss_date(x_oss_date).setSignature(signature).setSecurity_token(securityToken).setDir(uploadDir).setHost(host);}

OSSUtil.java

public class OSSUtil {private OSSUtil() {}/*** 定义日期时间格式,例如2023-12-03T13:00:00.000Z*/public static final String TIME_FORMAT_PATTERN = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'";public static byte[] getHmacSHA256(byte[] key, String data) {try {// 初始化HMAC密钥规格,指定算法为HMAC-SHA256并使用提供的密钥。SecretKeySpec secretKeySpec = new SecretKeySpec(key, "HmacSHA256");// 获取Mac实例,并通过getInstance方法指定使用HMAC-SHA256算法。Mac mac = Mac.getInstance("HmacSHA256");// 使用密钥初始化Mac对象。mac.init(secretKeySpec);// 执行HMAC计算,通过doFinal方法接收需要计算的数据并返回计算结果的数组。byte[] hmacBytes = mac.doFinal(data.getBytes());return hmacBytes;} catch (Exception e) {throw new RuntimeException("Failed to calculate HMAC-SHA256", e);}}/*** 通过指定有效的时长(秒)生成过期时间。** @param seconds 有效时长(秒)。* @return ISO8601 时间字符串,如:"2014-12-01T12:00:00.000Z"。*/public static String generateExpiration(long seconds) {// 获取当前时间戳(以秒为单位)long now = Instant.now().getEpochSecond();// 计算过期时间的时间戳long expirationTime = now + seconds;// 将时间戳转换为Instant对象,并格式化为ISO8601格式Instant instant = Instant.ofEpochSecond(expirationTime);// 定义时区为UTCZoneId zone = ZoneOffset.UTC;// 将 Instant 转换为 ZonedDateTimeZonedDateTime zonedDateTime = instant.atZone(zone);// 定义日期时间格式,例如2023-12-03T13:00:00.000ZDateTimeFormatter formatter = DateTimeFormatter.ofPattern(TIME_FORMAT_PATTERN);// 格式化日期时间String formattedDate = zonedDateTime.format(formatter);// 输出结果return formattedDate;}}

STSPolicyDTO.java

@Getter
@Setter
@Accessors(chain = true)
public class STSPolicyDTO {/*** 官方代码示例中给的“"OSS4-HMAC-SHA256"”*/private String version="OSS4-HMAC-SHA256";private String policy;private String x_oss_credential;private String x_oss_date;private String signature;private String security_token;private String dir;private String host;
}

提供接口

@RestController
@RequestMapping("/oss")
@Api("OSS文件上传验签")
public class AliOSSController {final AliOSSService ossService;public AliOSSController(AliOSSService ossService) {this.ossService = ossService;}/*** oss上传文件:使用服务端验签web直传的方式* 该接口提供web直传所必须的验签信息* 文档地址:https://help.aliyun.com/zh/oss/use-cases/obtain-signature-information-from-the-server-and-upload-data-to-oss?spm=a2c4g.11186623.help-menu-31815.d_6_1_0_0.386b4acdkrwKDc&scm=20140722.H_31926._.OR_help-T_cn~zh-V_1* @return*/@GetMapping("policy")@ApiOperation("STS验签V4版")public R<STSPolicyDTO> policy() throws JsonProcessingException {// UploadPolicyDTO uploadPolicy = ossService.getUploadPolicy();STSPolicyDTO uploadPolicy = ossService.getSTSUploadPolicy();return R.ok().data(uploadPolicy);}}

接口的响应数据示例


{"success": true,"code": 2000,"message": "成功","data": {"version": "OSS4-HMAC-SHA256","policy": "eyJleHBpcmF0aW9uIjoiMjAyNS0wNy0zMFQxNToyMjowNy4wMDBaIiwiY29uZGl0aW9ucyI6W3siYnVja2V0IjoiaWRvb3ktbWFsbCJ9LHsieC1vc3Mtc2VjdXJpdHktdG9rZW4iOiJDQUlTelFKMXE2RnQ1QjJ5ZlNqSXI1blFFZXo1aDVzVjRZYXpZM1BjZ1ZFZGFkcGl2cFB5aWp6MklIaE1lWEJoQStrZHR2b3duMnBaN3Z3Y2xyMXlSNWhDVkhiRGFjWkw0NDlNOEFTblJZUEV0cFFiWm1DelpjYjNkMUtJQWp2WGdlWHdBWXlnUHY2L0Y5NnBiMWZiN0Z3UnBaTHhhVFNsV1hHOExKU05rdVFKUjk4TFh3NitIMUVrYlpVc1VXa0Vrc0lCTW1iTFB2dUFLd1BqaG5HcWJIQmxvUTFoazJoeW04L2RxNCsra2tPRzBnU2xsYkJPKzltdWNzUDdNWmxXVWMwaEE0dnY3b3RmYmJIYzFTTmMwUjlPK1pwdGdiWk1rVFc5NVluRlhnQUF1VXpkYTdTTHFZYytkRlVuZk00OUFMVUJzL1gyME9CZ3Z1dmFtNVJIYk9USnNUek1PczYyWmZkRG9LT3NjSXZCWHI2eUpRamxvSElPQzZpd0xHL3pxUzBtVjJBNTlmOG1GQ0haMG9hWjZOSDlvOXdiODBKR0ZZRURvL1phcHNKdXFzSkpPdUtlcEE2QVZ0VW44QVhuSzkwYWdBRWloRDByMzE0TnNadUp6UHFkbkF3aUVXWjhWdWFvWlZUUzl0eTdmTW1vUTRIaGsrODE3U3BqeWVvMloycGo3T21zaFVWRmpKNFN5cjVsMWo2VFM3aVBqcFZlRG1xZjhtZ0tRc2F0bFdReHFwdk9MQmIray9QTktNei9kRXA4RFF3clg3S2x6b1RVRTA4bndKK0dqeEFFd0FkVWh3blBBbk14dVlXTEZrdUtZQ0FBIn0seyJ4LW9zcy1zaWduYXR1cmUtdmVyc2lvbiI6Ik9TUzQtSE1BQy1TSEEyNTYifSx7Ingtb3NzLWNyZWRlbnRpYWwiOiJTVFMuTlplWlZNakQ0VkRYYVVtZVFIZVVOUVZZaC8yMDI1MDczMC9jbi1jaGVuZ2R1L29zcy9hbGl5dW5fdjRfcmVxdWVzdCJ9LHsieC1vc3MtZGF0ZSI6IjIwMjUwNzMwVDE0MjIwN1oifSxbImNvbnRlbnQtbGVuZ3RoLXJhbmdlIiwxLDEwMjQwMDAwXSxbImVxIiwiJHN1Y2Nlc3NfYWN0aW9uX3N0YXR1cyIsIjIwMCJdLFsic3RhcnRzLXdpdGgiLCIka2V5IiwiYnJhbmQvMjAyNS0wNy0zMCJdXX0=","x_oss_credential": "STS.NZeZVMjD4VDXaUmeQHeUNQVYh/20250730/cn-chengdu/oss/aliyun_v4_request","x_oss_date": "20250730T142207Z","signature": "e583ba3040d9ac4544b4008f7193edf30fdef75cca6d4ca0e449150cf4904165","security_token": "CAISzQJ1q6Ft5B2yfSjIr5nQEez5h5sV4YazY3PcgVEdadpivpPyijz2IHhMeXBhA+kdtvown2pZ7vwclr1yR5hCVHbDacZL449M8ASnRYPEtpQbZmCzZcb3d1KIAjvXgeXwAYygPv6/F96pb1fb7FwRpZLxaTSlWXG8LJSNkuQJR98LXw6+H1EkbZUsUWkEksIBMmbLPvuAKwPjhnGqbHBloQ1hk2hym8/dq4++kkOG0gSllbBO+9mucsP7MZlWUc0hA4vv7otfbbHc1SNc0R9O+ZptgbZMkTW95YnFXgAAuUzda7SLqYc+dFUnfM49ALUBs/X20OBgvuvam5RHbOTJsTzMOs62ZfdDoKOscIvBXr6yJQjloHIOC6iwLG/zqS0mV2A59f8mFCHZ0oaZ6NH9o9wb80JGFYEDo/ZapsJuqsJJOuKepA6AVtUn8AXnK90agAEihD0r314NsZuJzPqdnAwiEWZ8VuaoZVTS9ty7fMmoQ4Hhk+817Spjyeo2Z2pj7OmshUVFjJ4Syr5l1j6TS7iPjpVeDmqf8mgKQsatlWQxqpvOLBb+k/PNKMz/dEp8DQwrX7KlzoTUE08nwJ+GjxAEwAdUhwnPAnMxuYWLFkuKYCAA","dir": "brand/2025-07-30","host": "目标bucket的公网访问域名"}
}

Apifox模拟Web端文件直传

文件上传的地址,就是你自己目标bucket的公网访问域名,也可以直接从上面接口的响应字段host获取,这部分就是结合自己的前端项目自行开发。将上传的参数名称做个简单的说明。
请求参数名称:

{"success_action_status", "200""policy", data.policy"x-oss-signature", data.signature"x-oss-signature-version", "OSS4-HMAC-SHA256""x-oss-credential", data.x_oss_credential"x-oss-date", data.x_oss_date"key", data.dir + file.name // 文件名"x-oss-security-token", data.security_token"file", file); // file 必须为最后一个表单域
}                

在这里插入图片描述
没啥文章功底,主要是站在自己的角度一通记录而已;多包涵,欢迎在评论区讨论共同学习。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/pingmian/91133.shtml
繁体地址,请注明出处:http://hk.pswp.cn/pingmian/91133.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

uniapp实现微信小程序导航功能

1.导航按钮<button click"navigation()">导航到仓库</button>2.导航功能const navigation (item) > {let address item.province item.city item.district item.address //地址let latitude Number(item.latitude) …

07.4-使用 use 关键字引入路径

使用 use 关键字引入路径 每次调用函数时都必须写出完整路径&#xff0c;可能会感觉不便且重复。在清单7-7中&#xff0c;无论我们选择绝对路径还是相对路径来调用 add_to_waitlist 函数&#xff0c;每次调用时都必须指定 front_of_house 和 hosting。幸运的是&#xff0c;有一…

7.Linux :进程管理,进程控制与计划任务

Linux &#xff1a;进程管理&#xff0c;进程控制与计划任务 一、进程管理 1. 进程与程序 程序&#xff1a;静态的可执行文件&#xff08;存储于磁盘&#xff09;。进程&#xff1a;动态执行的程序实例&#xff08;占用CPU/内存&#xff09;。 2. 查看进程命令作用常用组合ps静…

Matplotlib(四)- 图表样式美化

文章目录一、Matplotlib图表样式介绍1. 图表样式简介2. 默认图表样式2.1 查看默认配置2.2 常用的配置3. 图表样式修改3.1 局部修改3.1.1 通过绘图方法设置参数修改3.1.2 通过rcParams修改3.1.3 通过rc()方法修改3.2 全局修改二、颜色设置1. 颜色的三种表示方式1.1 颜色单词1.2 …

三十四、【Linux常用工具】rsync+inotify实时同步演示

实时同步演示技术架构全景核心组件详解1. inotify 内核子系统2. Rsync 高效同步工具实践演示一、环境准备与安装1. 检查内核支持2. 安装 inotify-tools二、配置 Rsync 服务端&#xff08;目标机&#xff09;1. 创建 Rsync 配置文件2. 启动 Rsync 守护进程三、配置实时同步脚本&…

windows环境下MySQL 8.0 修改或重置密码

windows环境下MySQL 8.0 修改或重置密码 1打开命令窗口cmd&#xff0c;输入命令&#xff1a;net stop mysql&#xff0c; 停止MySQL服务&#xff0c; 开启跳过密码验证登录的MySQL服务 2输入命令 mysqld --console --skip-grant-tables --shared-memory 再打开一个新的cmd&…

基于YOLOP与GAN的图像修复与防御系统设计与实现

基于YOLOP与GAN的图像修复与防御系统设计与实现 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家&#xff0c;觉得好请收藏。点击跳转到网站。 1. 引言 1.1 研究背景 随着深度学习技术在计算机视觉领域的…

将目录文件转移到D盘,使之后的下载缓存数据转移,不再存入c盘

将 C:\Users 文件夹&#xff08;用户文件夹&#xff09;转移到其他盘是一个复杂且风险较高的操作。C:\Users 文件夹包含了系统中每个用户的个人数据和配置文件&#xff0c;修改这个路径可能会导致系统出现问题&#xff0c;包括程序无法正常工作或无法登录。因此&#xff0c; 强…

Cesium大气散射效果

由于做全球体积云效果的需要&#xff0c;再来研究下大气散射效果和体积云类似&#xff0c;关于大气散射颜色计算的过程也仅发生在这两个球体之间。如图所示。计算从相机出发的视线与球壳的交点&#xff0c;如果不相交&#xff0c;则该视线方向上不会发生大气散射&#xff0c;直…

预过滤环境光贴图制作教程:第二步 - 生成环境贴图图集

核心目标 本步骤的核心是生成一张包含 6 级分辨率的环境贴图图集(envAtlas),实现: 将第一步的立方体贴图(sourceCube)重新映射为等矩形投影(适合存储和采样); 生成 6 级不同分辨率的等矩形数据(0 级最高清,5 级最模糊); 用 RGBP 编码压缩 HDR 数据(平衡精度与存…

1. ESP开发之实体按键(KEYPADBUTTON)控制LVGL控件

说明LV_INDEV_TYPE_BUTTON的使用LV_INDEV_TYPE_KEYPAD的使用 说明 本实验使用LVGL版本为v9.2 LVGL中有四种输入设备,如下LV_INDEV_TYPE_POINTER, /**< Touch pad, mouse, external button*/ LV_INDEV_TYPE_KEYPAD, /**< Keypad or keyboard*/ LV_INDEV_TYPE_BUTTON, /*…

C++:STL中list的使用和模拟实现

C中的list是标准模板库&#xff08;STL&#xff09;提供的双向链表容器&#xff0c;支持高效的元素插入和删除操作。在上一篇中讲解了vector的使用和模拟实现&#xff0c;vector是具有连续的空间&#xff0c;迭代器是可以随机的&#xff0c;而list却于vector不同&#xff0c;li…

【编号58-61】我国四大高原矢量示意图shp数据

今天分享的是&#xff1a;中国四大高原&#xff0c;分别是青藏高原、内蒙古高原、黄土高原、云贵高原。青藏高原位置与范围&#xff1a;位于中国西南部&#xff0c;包括西藏、青海的全部&#xff0c;川西高原及滇西北高原等部分地区。它的边界&#xff0c;向东是横断山脉&#…

【AI落地应用实战】利用 Amazon Bedrock Claude3 打造个性化 AI Character 应用

目录一、引言&#xff1a;AI Character应用的市场前景与技术基础二、技术架构设计2.1、整体方案概述2.2、核心组件介绍2.3、部署架构图三、系统部署方案3.1、方案总述3.2、实践流程1️⃣. Bedrock 配置2️⃣. 安装 SillyTavern3️⃣. 配置 SillyTavern 使用 Claude3 模型4️⃣.…

Java常用日志框架介绍

Java提供了很多第三方的日志框架可供使用&#xff0c;按照现在的设计理念&#xff0c;一般把日志框架分成门面(Facade)部分和具体实现(Implementation)部分&#xff0c;门面(Facade)提供了抽象的api规范&#xff0c;实现(Implementation)负责实现api完成具体的日志记录功能。开…

飞书 —— 多维表格 —— AI生成

1.添加关联账号&#xff1a; 2.获取密钥 ARK_API_KEY 进入火山引擎服务页面&#xff1a;https://console.volcengine.com/ark/region:arkcn-beijing/model/detail?Iddeepseek-r1 先进入推理模型 > 快捷API接入 再去在线推理中创建推理接入点 点击新创建好的接入点的API调…

我的世界模组开发教程——资源(1)

下面我们来研究一下ResourceLocation,每次开启游戏时都会报这个错误:“ResourceLocation 中的 ResourceLocation(String) 已过时, 且标记为待删除”,下面我们来详细的研究一下这个类 ResourceLocation ResourceLocation 是 Minecraft 中用于唯一标识游戏资源的核心类(如方…

我从 Web2 转型到 Web3 的 9 条经验总结

作者&#xff1a;Forte Group 高级区块链工程师 Yurii Kovalchuk原文&#xff1a;https://cryptoslate.com/why-i-left-web2-for-web3-and-why-you-might-too/三年前&#xff0c;我做出了一个彻底改变职业轨迹的决定&#xff1a;离开熟悉的 Web2&#xff0c;投身于深邃、混乱却…

【MySQL 数据库】MySQL索引特性(一)磁盘存储定位扇区InnoDB页

文章目录没有索引&#xff0c;可能会有什么问题二、认识磁盘2.1 MySQL与存储2.2 磁盘&#xff1a;2.3 扇区2.4 定位扇区2.5 结论三、三者作用流程&#xff08;磁盘&#xff0c;块&#xff0c;InnoDB页&#xff09;四、MySQL与磁盘交互基本单位五、建立共识&#x1f6a9;总结没有…

2419. 按位与最大的最长子数组

Problem: 2419. 按位与最大的最长子数组 文章目录思路解题过程复杂度Code思路 按位异或只会让数值越来越小&#xff0c;因此最长的连续按位与的最大值只存在于连续最大值中。 解题过程 遍历数组取出最大值&#xff0c;再遍历找到每一次连续最大值&#xff0c;从中取出最长的连续…