Spring Cloud + Vue前后端分离-第10章 基于阿里云OSS的文件上传
源代码在GitHub - 629y/course: Spring Cloud + Vue前后端分离-在线课程
Spring Cloud + Vue前后端分离-第10章 基于阿里云OSS的文件上传
前面介绍的文件上传是基于本地文件服务器的文件上传,但是自己搭文件服务器会有很多运维的问题,比如磁盘满了要扩容,高峰期要增加带宽,低谷期要减少带宽,为了安全,我们还要对文件做备份等等。
所以一般会选择云平台来存储文件,云平台有很多,比如阿里云、腾讯云、百度云等,云平台做的最好的是亚马逊,我们这里选择国内最大的阿里云。
10-1 阿里云OSS简介
面向海量数据规模的分布式存储服务
从浏览器通过ECS( 服务器)访问OSS,算内网访问,不算流量费,但是要考虑ECS的带宽问题。从浏览器直接访问OSS资源,算外网访问OSS,需付流量费,但是可以不用考虑带宽。

10-2 基于OSS接口的文件上传
阿里云OSS控台的使用




bucket:存储空间,名称必须是全阿里云唯一





这个文件地址可以直接打开观看
基于OSS接口实现文件上传
1.大文件断点续传与极速秒传:基于OSS接口实现文件上传,增加文件追加上传oss-append 和简单上传oss-simple







pom.xml

OssController.java
package com.course.file.controller.admin;import com.alibaba.fastjson.JSONObject;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.model.AppendObjectRequest;
import com.aliyun.oss.model.AppendObjectResult;
import com.aliyun.oss.model.ObjectMetadata;
import com.aliyun.oss.model.PutObjectRequest;
import com.course.server.dto.FileDto;
import com.course.server.dto.ResponseDto;
import com.course.server.enums.FileUseEnum;
import com.course.server.service.FileService;
import com.course.server.util.Base64ToMultipartFile;
import com.course.server.util.UuidUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;import javax.annotation.Resource;
import java.io.ByteArrayInputStream;@RestController
@RequestMapping("/admin")
public class OssController {private static final Logger LOG = LoggerFactory.getLogger(OssController.class);@Value("${oss.accessKeyId}")private String accessKeyId;@Value("${oss.accessKeySecret}")private String accessKeySecret;@Value("${oss.endpoint}")private String endpoint;@Value("${oss.bucket}")private String bucket;@Value("${oss.domain}")private String ossDomain;public static final String BUSINESS_NAME = "文件上传";@Resourceprivate FileService fileService;@PostMapping("/oss-append")public ResponseDto fileUpload(@RequestBody FileDto fileDto) throws Exception {LOG.info("上传文件开始");String use = fileDto.getUse();String key = fileDto.getKey();String suffix = fileDto.getSuffix();Integer shardIndex = fileDto.getShardIndex();Integer shardSize = fileDto.getShardSize();String shardBase64 = fileDto.getShard();MultipartFile shard = Base64ToMultipartFile.base64ToMultipart(shardBase64);// 保存文件到本地FileUseEnum useEnum = FileUseEnum.getByCode(use);// //如果文件夹不存在则创建String dir = useEnum.name().toLowerCase();
// File fullDir = new File(FILE_PATH + dir);
// if (!fullDir.exists()) {
// fullDir.mkdir();
// }// String path = dir + File.separator + key + "." + suffix + "." + fileDto.getShardIndex();String path = new StringBuffer(dir).append("/").append(key).append(".").append(suffix).toString(); // course\6sfSqfOwzmik4A4icMYuUe.mp4
// String localPath = new StringBuffer(path)
// .append(".")
// .append(fileDto.getShardIndex())
// .toString(); // course\6sfSqfOwzmik4A4icMYuUe.mp4.1
// String fullPath = FILE_PATH + localPath;
// File dest = new File(fullPath);
// shard.transferTo(dest);
// LOG.info(dest.getAbsolutePath());// 创建OSSClient实例。OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);ObjectMetadata meta = new ObjectMetadata();
// 指定上传的内容类型。meta.setContentType("text/plain");// 通过AppendObjectRequest设置多个参数。AppendObjectRequest appendObjectRequest = new AppendObjectRequest(bucket, path, new ByteArrayInputStream(shard.getBytes()), meta);// 通过AppendObjectRequest设置单个参数。// 设置存储空间名称。//appendObjectRequest.setBucketName("<yourBucketName>");// 设置文件名称。//appendObjectRequest.setKey("<yourObjectName>");// 设置待追加的内容。有两种可选类型:InputStream类型和File类型。这里为InputStream类型。//appendObjectRequest.setInputStream(new ByteArrayInputStream(content1.getBytes()));// 设置待追加的内容。有两种可选类型:InputStream类型和File类型。这里为File类型。//appendObjectRequest.setFile(new File("<yourLocalFile>"));// 指定文件的元信息,第一次追加时有效。//appendObjectRequest.setMetadata(meta);// 第一次追加。// 设置文件的追加位置。
// appendObjectRequest.setPosition(0L);appendObjectRequest.setPosition((long) ((shardIndex - 1) * shardSize));AppendObjectResult appendObjectResult = ossClient.appendObject(appendObjectRequest);// 文件的64位CRC值。此值根据ECMA-182标准计算得出。System.out.println(appendObjectResult.getObjectCRC());System.out.println(JSONObject.toJSONString(appendObjectResult));// // 第二次追加。
// // nextPosition指明下一次请求中应当提供的Position,即文件当前的长度。
// appendObjectRequest.setPosition(appendObjectResult.getNextPosition());
// appendObjectRequest.setInputStream(new ByteArrayInputStream(content2.getBytes()));
// appendObjectResult = ossClient.appendObject(appendObjectRequest);
//
// // 第三次追加。
// appendObjectRequest.setPosition(appendObjectResult.getNextPosition());
// appendObjectRequest.setInputStream(new ByteArrayInputStream(content3.getBytes()));
// appendObjectResult = ossClient.appendObject(appendObjectRequest);// 关闭OSSClient。ossClient.shutdown();LOG.info("保存文件记录开始");fileDto.setPath(path);fileService.save(fileDto);ResponseDto responseDto = new ResponseDto();fileDto.setPath(ossDomain + path);responseDto.setContent(fileDto);// if (fileDto.getShardIndex().equals(fileDto.getShardTotal())) {
// this.merge(fileDto);
// }return responseDto;}@PostMapping("/oss-simple")public ResponseDto fileUpload(@RequestParam MultipartFile file, String use) throws Exception {LOG.info("上传文件开始");FileUseEnum useEnum = FileUseEnum.getByCode(use);String key = UuidUtil.getShortUuid();String fileName = file.getOriginalFilename();String suffix = fileName.substring(fileName.lastIndexOf(".") + 1).toLowerCase();String dir = useEnum.name().toLowerCase();String path = dir + "/" + key + "." + suffix;// 创建OSSClient实例。OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);// 创建PutObjectRequest对象。
// String content = "Hello OSS";// <yourObjectName>表示上传文件到OSS时需要指定包含文件后缀在内的完整路径,例如abc/efg/123.jpg。PutObjectRequest putObjectRequest = new PutObjectRequest(bucket, path, new ByteArrayInputStream(file.getBytes()));// 如果需要上传时设置存储类型与访问权限,请参考以下示例代码。// ObjectMetadata metadata = new ObjectMetadata();// metadata.setHeader(OSSHeaders.OSS_STORAGE_CLASS, StorageClass.Standard.toString());// metadata.setObjectAcl(CannedAccessControlList.Private);// putObjectRequest.setMetadata(metadata);// 上传字符串。ossClient.putObject(putObjectRequest);// LOG.info("保存文件记录开始");
// fileDto.setPath(path);
// fileService.save(fileDto);ResponseDto responseDto = new ResponseDto();FileDto fileDto = new FileDto();fileDto.setPath(ossDomain + path);responseDto.setContent(fileDto);return responseDto;}
}
application.properties

big-file.vue

file.vue

演示:头像上传是用的单文件传输到OSS;视频上传是用的分片传输到OSS
teacher.vue


测试
上传视频和头像



10-3{white}阿里云视频点播服务介绍{white}{white}
阿里云视频点播服务介绍

视频点播控台的使用



















视频点播帮助文档概览







10-4 基于OSS原生SDK上传视频到点播服务
VOD上传并加密转码
VOD上传并加密转码
1.视频加密与授权播放:基于 OSS原生SDK上传视频到点播服务,官方示例代码
pom.xml(course)

pom.xml(server)

VodUtil.java
package com.course.server.util;import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.aliyun.oss.OSSClient;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.http.FormatType;
import com.aliyuncs.profile.DefaultProfile;
import com.aliyuncs.vod.model.v20170321.*;
import org.apache.commons.codec.binary.Base64;import java.io.File;
import java.io.InputStream;public class VodUtil {/*** 使用AK初始化VOD客户端* @param accessKeyId* @param accessKeySecret* @return* @throws ClientException*/public static DefaultAcsClient initVodClient(String accessKeyId, String accessKeySecret) throws ClientException {// 点播服务接入区域,国内请填cn-shanghai,其他区域请参考文档[点播中心](~~98194~~)String regionId = "cn-shanghai";DefaultProfile profile = DefaultProfile.getProfile(regionId, accessKeyId, accessKeySecret);DefaultAcsClient client = new DefaultAcsClient(profile);return client;}/*** 获取视频上传地址和凭证* @param vodClient* @return* @throws ClientException*/public static CreateUploadVideoResponse createUploadVideo(DefaultAcsClient vodClient, String fileName) throws ClientException {CreateUploadVideoRequest request = new CreateUploadVideoRequest();request.setFileName(fileName);request.setTitle(fileName);//request.setDescription("this is desc");//request.setTags("tag1,tag2");
// request.setCoverURL("http://vod.aliyun.com/test_cover_url.jpg");
// request.setCateId(1000115308L);
// request.setTemplateGroupId("78fffb8c0c2426efd5baaaafed76fe36");//request.setWorkflowId("");//request.setStorageLocation("");//request.setAppId("app-1000000");//设置请求超时时间request.setSysReadTimeout(1000);request.setSysConnectTimeout(1000);return vodClient.getAcsResponse(request);}/*** 使用上传凭证和地址初始化OSS客户端(注意需要先Base64解码并Json Decode再传入)* @param uploadAuth* @param uploadAddress* @return*/public static OSSClient initOssClient(JSONObject uploadAuth, JSONObject uploadAddress) {String endpoint = uploadAddress.getString("Endpoint");String accessKeyId = uploadAuth.getString("AccessKeyId");String accessKeySecret = uploadAuth.getString("AccessKeySecret");String securityToken = uploadAuth.getString("SecurityToken");return new OSSClient(endpoint, accessKeyId, accessKeySecret, securityToken);}/*** 简单上传* @param ossClient* @param uploadAddress* @param inputStream*/public static void uploadLocalFile(OSSClient ossClient, JSONObject uploadAddress, InputStream inputStream){String bucketName = uploadAddress.getString("Bucket");String objectName = uploadAddress.getString("FileName");// 单文件上传ossClient.putObject(bucketName, objectName, inputStream);/* 视频点播不支持追加上传// 追加上传ObjectMetadata meta = new ObjectMetadata();meta.setContentType("text/plain");AppendObjectRequest request = new AppendObjectRequest(bucketName, objectName, file, meta);request.setPosition(0L);ossClient.appendObject(request);*/}/*** 上传本地文件* @param ossClient* @param uploadAddress* @param localFile*/public static void uploadLocalFile(OSSClient ossClient, JSONObject uploadAddress, String localFile){String bucketName = uploadAddress.getString("Bucket");String objectName = uploadAddress.getString("FileName");File file = new File(localFile);// 单文件上传ossClient.putObject(bucketName, objectName, file);/* 视频点播不支持追加上传// 追加上传ObjectMetadata meta = new ObjectMetadata();meta.setContentType("text/plain");AppendObjectRequest request = new AppendObjectRequest(bucketName, objectName, file, meta);request.setPosition(0L);ossClient.appendObject(request);*/}/*** 刷新上传凭证* @param vodClient* @return* @throws ClientException*/public static RefreshUploadVideoResponse refreshUploadVideo(DefaultAcsClient vodClient) throws ClientException {RefreshUploadVideoRequest request = new RefreshUploadVideoRequest();request.setAcceptFormat(FormatType.JSON);request.setVideoId("VideoId");//设置请求超时时间request.setSysReadTimeout(1000);request.setSysConnectTimeout(1000);return vodClient.getAcsResponse(request);}/*** 获取源文件信息* @param client 发送请求客户端* @return GetMezzanineInfoResponse 获取源文件信息响应数据* @throws Exception*/public static GetMezzanineInfoResponse getMezzanineInfo(DefaultAcsClient client, String videoId) throws Exception {GetMezzanineInfoRequest request = new GetMezzanineInfoRequest();request.setVideoId(videoId);//源片下载地址过期时间request.setAuthTimeout(3600L);return client.getAcsResponse(request);}/*** 获取播放凭证函数* @param client* @return* @throws Exception*/public static GetVideoPlayAuthResponse getVideoPlayAuth(DefaultAcsClient client, String videoId) throws Exception {GetVideoPlayAuthRequest request = new GetVideoPlayAuthRequest();request.setVideoId(videoId);return client.getAcsResponse(request);}public static void main(String[] argv) {//您的AccessKeyIdString accessKeyId = "xxxxxxxxxxxxx";//您的AccessKeySecretString accessKeySecret = "xxxxxxxxxxxxx";//需要上传到VOD的本地视频文件的完整路径,需要包含文件扩展名String localFile = "/Users/zhaoxiaoyun/Downloads/fourcats.mp4";try {// 初始化VOD客户端并获取上传地址和凭证DefaultAcsClient vodClient = initVodClient(accessKeyId, accessKeySecret);String fileName = "test.mp4";CreateUploadVideoResponse createUploadVideoResponse = createUploadVideo(vodClient, fileName);// 执行成功会返回VideoId、UploadAddress和UploadAuthString videoId = createUploadVideoResponse.getVideoId();JSONObject uploadAuth = JSONObject.parseObject(Base64.decodeBase64(createUploadVideoResponse.getUploadAuth()), JSONObject.class);JSONObject uploadAddress = JSONObject.parseObject(Base64.decodeBase64(createUploadVideoResponse.getUploadAddress()), JSONObject.class);// 使用UploadAuth和UploadAddress初始化OSS客户端OSSClient ossClient = initOssClient(uploadAuth, uploadAddress);// 上传文件,注意是同步上传会阻塞等待,耗时与文件大小和网络上行带宽有关uploadLocalFile(ossClient, uploadAddress, localFile);System.out.println("上传视频成功, VideoId : " + videoId); // 7d6b8c07ab48456e932187080f42e88fGetMezzanineInfoResponse response = new GetMezzanineInfoResponse();response = getMezzanineInfo(vodClient, videoId);System.out.println("获取视频信息, response : " + JSON.toJSONString(response));} catch (Exception e) {System.out.println("上传视频失败, ErrorMessage : " + e.getLocalizedMessage());}}
}
记得修改自己的


VOD上传到指定分类,并自动转码
1.视频加密与授权播放:基于 OSS原生SDK上传视频到点播服务,上传到指定分类,并自动转码
VodUtil.java





视频点播不支持追加上传
1.视频加密与授权播放:基于 OSS原生SDK上传视频到点播服务,视频点播不支持追加上传
官方示例中,用的是简单上传putObject ,我们要改成我们需要的追加上传
但是有严格封装编码要求的文件类型,都是不支持追加方式上传的;比如音视频、图片等,上传到视频点播不支持追加上传
VodUtil.java

效果就不演示了,感兴趣的自己尝试一下,把这段代码打开,把上面的单文件上传注释,然后看效果,是一直在上传,但是无法上传成功!
项目集成VOD上传
小节增加vod字段
1.视频加密与授权播放:小节增加vod字段
由于视频点播不支持追加上传,我们只能改成单文件传
all.sql

generatorConfig.xml

SectionDto.java

section.vue

简单快速的方案:在阿里云控台做文件上传和转码,然后将vod复制到我们自己的控台

增加vod组件,用于上传视频到视频点播服务
1.视频加密与授权播放:增加vod组件,用于上传视频到视频点播服务
big-file.vue



vod组件就是对big-file组件做了一层封装。程序员天然喜欢对代码做封装,要注意度,封装得越多,灵活度就越低
vod.vue
<template><big-file v-bind:input-id="inputId"v-bind:text="text"v-bind:suffixs="suffixs"v-bind:use="use"v-bind:after-upload="afterUpload"v-bind:shard-size="shardSize"v-bind:url="'oss-append'"></big-file>
</template><script>
import BigFile from "./big-file";
export default {name: "vod",components: {BigFile},props: {text: {default: "上传VOD"},inputId: {default: "vod-upload"},suffixs: {default: []},use: {default: ""},shardSize: {default: 50 * 1024},afterUpload: {type: Function,default: null},},
}
</script>
目前为止,vod和big-file功能一样,需要先测试下vod组件是否可用
section.vue


我们在js里对video赋值,vue会监听到值的变化,并渲染视频控件。如果还没渲染完,我们就去获取时长,这时就会得到NaN,所以需要加延时获取

测试,记得先清空数据库和oss文件



file表增加vod字段
1.视频加密与授权播放:file表增加vod字段
all.sql


generatorConfig.xml

FileDto.java

增加视频点播文件上传功能
1.视频加密与授权播放:增加视频点播文件上传功能
application.properties

vod.vue

由于视频点播不支持追加上传,所以使用vod组件进行上传的,只能有一个分片

section.vue

获取到的可播放地址是有时效的,所以就算保存到数据库也会过期,没用。以后会根据vod来播放。

文件检查时,根据是否是视频点播文件来获取视频信息
1.视频加密与授权播放:文件检查时,根据是否是视频点播文件来获取视频信息
UploadController.java


测试

10-6 视频授权播放功能开发
阿里云播放器的基本使用
1.视频加密与授权播放:集成阿里云播放器,制作player播放器组件
player.vue
<template><div v-bind:id="playerId">
<!--要做成动态的,所以不在这个地方写了-->
<!-- <div class="prism-player" id="J_prismPlayer"></div>--></div>
</template>
<script>
export default {name: "player",props: {playerId: {default: "player-div"},},data: function () {return {aliPlayer: {},//播放器实例}},methods: {playUrl(url) {let _this = this;console.log("开始播放:", url);//如果已经有播放器了,则将播放器div删除if (_this.aliPlayer) {_this.aliPlayer = null;$("#J_prismPlayer").remove();}// 初始化播放器$("#" + _this.playerId).append("<div class=\"prism-player\" id=\"J_prismPlayer\"></div>");_this.aliPlayer = new Aliplayer({id: "J_prismPlayer",width: '100%',autoplay: false,source: url,cover: 'http://imooc-coursemac.oss-cn-shanghai.aliyuncs.com/头像1.jpg',}, function (player) {console.log('播放器创建好了。')});},}
}
</script>
index.html


section.vue

video控件隐藏掉,不要删除,要通过它获取时长。也可以通过视频点播的API去获取视频时长。


测试


功能更强,可以倍速等等
获取vod授权码并授权播放
1.视频加密与授权播放:获取vod授权码并授权播放,需要在存储管理中把权限设置成公共读
默认是私有的,更改为公共读

VodUtil.java

VodController.java

player.vue
一个页面可能会放多个player组件,所以需要把id做成动态变化的,一个页面的元素,id值要是唯一的。



modal-player.vue
带有模态框的播放器组件modal-player,里面包含了player组件
<template><div id="player-modal" class="modal" tabindex="-1" role="dialog"><div class="modal-dialog" role="document"><div class="modal-content"><div class="modal-body"><player v-bind:player-id="'modal-player-div'"ref="player"></player></div></div></div></div>
</template>
<script>
import Player from "./player";
export default {name: 'modal-player',components: {Player},data: function () {return {aliPlayer: {}, // 播放器实例}},methods: {playUrl(url) {let _this = this;_this.$refs.player.playUrl(url);},playVod(vod) {let _this = this;_this.$refs.player.playVod(vod);$("#player-modal").modal("show");}}
}
</script><style scoped>
#player-modal .modal-body {padding: 0;
}
</style>
section.vue




测试



相关文章:
Spring Cloud + Vue前后端分离-第10章 基于阿里云OSS的文件上传
源代码在GitHub - 629y/course: Spring Cloud Vue前后端分离-在线课程 Spring Cloud Vue前后端分离-第10章 基于阿里云OSS的文件上传 前面介绍的文件上传是基于本地文件服务器的文件上传,但是自己搭文件服务器会有很多运维的问题,比如磁盘满了要扩容…...
C++ 中的耗时计算函数
#include <time.h>int clock_gettime (clockid_t clock_id, struct timespec *tp) 获取当前 clock_id 的时钟值并存储在 tp 中。 其中 tp 是一个 timespec 结构体,在 time.h 头文件中定义: #include <time.h>:struct timespec {time_t t…...
【Element】el-form和el-table嵌套实现表格编辑并提交表单校验
一、背景 页面需要用到表格采集用户数据,提交时进行表单校验;即表格中嵌套着表单,保存时进行表单校验 二、功能实现 2.1、el-form和el-table嵌套说明 ① :model"formData" 给表单绑定数据,formData是表单的数据对象 …...
初识Winform
什么是winform? WinForms(Windows Forms)是Microsoft .NET框架中的一个用户界面(UI)技术,用于创建Windows应用程序。它提供了一组用于构建图形用户界面的类和控件,以及与用户交互的事件模型。 …...
Redis:原理速成+项目实战——Redis实战5(互斥锁、逻辑过期解决缓存击穿问题)
👨🎓作者简介:一位大四、研0学生,正在努力准备大四暑假的实习 🌌上期文章:Redis:原理速成项目实战——Redis实战4(解决Redis缓存穿透、雪崩、击穿) 📚订阅专…...
前端优化之一:dns预获取 dns-prefetch 提升页面载入速度
问题:怎么做到dns域解析? 用于优化网站页面的图片 问题:怎么提升网站性能? dns域解析,是提升网站的一个办法。 DNS Prefetch,即DNS预获取,是前端优化的一部分。 一般来说,在前端…...
C语言中一些基本数据类型的典型大小
char:通常是1字节。表示一个字符。int:通常在现代系统中是4字节(但这取决于编译器和架构,有时可能是2字节)。float:通常是4字节。double:通常是8字节。short 和 short int:通常是2字…...
[C/C++]排序算法 快速排序 (递归与非递归)
目录 🚩概念: 🚩实现: ⚡1.hoare ⚡2.挖坑法 ⚡3.双指针法 🚩快速排序递归实现 🚩快速排序非递归实现 🚩概念: 通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据比另一部分的所有…...
『年度总结』逐梦编程之始:我的2023学习回顾与展望
目录 前言 我与Python 我与C语言 第一篇正式博客: 第二篇正式博客(扫雷): 指针学习笔记: C语言学习笔记: 我与数据结构: yuan 这篇博客,我将回顾2023年编程之旅的起点,同时展…...
MyBatis学习二:Mapper代理开发、配置文件完成增删改查、注解开发
前言 公司要求没办法,前端也要了解一下后端知识,这里记录一下自己的学习 学习教程:黑马mybatis教程全套视频教程,2天Mybatis框架从入门到精通 文档: https://mybatis.net.cn/index.html Mapper代理开发 目的 解决…...
【React系列】受控非受控组件
本文来自#React系列教程:https://mp.weixin.qq.com/mp/appmsgalbum?__bizMzg5MDAzNzkwNA&actiongetalbum&album_id1566025152667107329) 一. refs 的使用 在React的开发模式中,通常情况下不需要、也不建议直接操作DOM原生,但是某些…...
OpenCV-Python(22):2D直方图
目标 了解图像的2D直方图绘制2D直方图 介绍 在前面的部分我们介绍了如何绘制一维直方图,之所以称为一维,是因为我们只考虑了图像的一个特征:灰度值。但是在2D 直方图中我们就需要考虑两个图像特征。对于彩色图像的直方图通常情况下我们需要…...
Kubernetes 100个常用命令
本文简单总结关于使用 Kubectl 进行 Kubernetes 诊断的指南。列出了 100 个 Kubectl 命令,这些命令对于诊断 Kubernetes 集群中的问题非常有用。这些问题包括但不限于: 集群信息 Pod 诊断 服务诊断 部署诊断 网络诊断 持久卷和持久卷声明诊断 资源…...
labuladong日常刷题-差分数组 | LeetCode 1109航班预定统计 | 花式遍历 151反转字符串里的单词
差分数组–前缀和数组的升级 LeetCode 1109 航班预定统计 2024.1.1 题目链接labuladong讲解[链接] class Solution { public:vector<int> corpFlightBookings(vector<vector<int>>& bookings, int n) {//构建航班人数数组,数组大小为n,初…...
HbuilderX中的git的使用
原文链接https://blog.csdn.net/Aom_yt/article/details/119924356...
LeetCode每日一题 | 1944. 队列中可以看到的人数
文章目录 队列中可以看到的人数题目描述问题分析程序代码(Golang 版本) 队列中可以看到的人数 题目描述 原题链接 有 n 个人排成一个队列,从左到右 编号为 0 到 n - 1 。给你以一个整数数组 heights ,每个整数 互不相同ÿ…...
React16源码: JSX2JS及React.createElement源码实现
JSX 到 Javascript 的转换 React中的 JSX 类似于 Vue中的template模板文件,Vue是基于编译时将template模板转换成render函数在React中,JSX是类似于html和javascript混编的语法,而javascript是真的javascript, html并非真的html它的可阅读性可…...
整理composer安装版本的python脚本
整理composer安装版本的python脚本 脚本实现的功能是去除composer安装命令后的版本号 def remove_version_numbers(commands):"""Remove version numbers from composer require commands.Args:commands (list of str): List of composer require commands.Retu…...
十、基本对话框大集合(Qt5 GUI系列)
目录 一、设计需求 二、实现代码 三、代码解析 四、总结 一、设计需求 Qt提供了很多标准的对话框。例如标准文件对话框(QFileDialog)、标准颜色对话框(QColorDialog)、标准字体对话框 (QFontDialog)、标准输入对话框 (QInputDialog) 及消息对话框 (QMessageBox)。本文展示各…...
大A又跌了
才开盘几天,又开始下跌了。生活更加苦难。期待高深算法。...
盘古信息PCB行业解决方案:以全域场景重构,激活智造新未来
一、破局:PCB行业的时代之问 在数字经济蓬勃发展的浪潮中,PCB(印制电路板)作为 “电子产品之母”,其重要性愈发凸显。随着 5G、人工智能等新兴技术的加速渗透,PCB行业面临着前所未有的挑战与机遇。产品迭代…...
连锁超市冷库节能解决方案:如何实现超市降本增效
在连锁超市冷库运营中,高能耗、设备损耗快、人工管理低效等问题长期困扰企业。御控冷库节能解决方案通过智能控制化霜、按需化霜、实时监控、故障诊断、自动预警、远程控制开关六大核心技术,实现年省电费15%-60%,且不改动原有装备、安装快捷、…...
Golang dig框架与GraphQL的完美结合
将 Go 的 Dig 依赖注入框架与 GraphQL 结合使用,可以显著提升应用程序的可维护性、可测试性以及灵活性。 Dig 是一个强大的依赖注入容器,能够帮助开发者更好地管理复杂的依赖关系,而 GraphQL 则是一种用于 API 的查询语言,能够提…...
【算法训练营Day07】字符串part1
文章目录 反转字符串反转字符串II替换数字 反转字符串 题目链接:344. 反转字符串 双指针法,两个指针的元素直接调转即可 class Solution {public void reverseString(char[] s) {int head 0;int end s.length - 1;while(head < end) {char temp …...
Qt Http Server模块功能及架构
Qt Http Server 是 Qt 6.0 中引入的一个新模块,它提供了一个轻量级的 HTTP 服务器实现,主要用于构建基于 HTTP 的应用程序和服务。 功能介绍: 主要功能 HTTP服务器功能: 支持 HTTP/1.1 协议 简单的请求/响应处理模型 支持 GET…...
Psychopy音频的使用
Psychopy音频的使用 本文主要解决以下问题: 指定音频引擎与设备;播放音频文件 本文所使用的环境: Python3.10 numpy2.2.6 psychopy2025.1.1 psychtoolbox3.0.19.14 一、音频配置 Psychopy文档链接为Sound - for audio playback — Psy…...
【C++从零实现Json-Rpc框架】第六弹 —— 服务端模块划分
一、项目背景回顾 前五弹完成了Json-Rpc协议解析、请求处理、客户端调用等基础模块搭建。 本弹重点聚焦于服务端的模块划分与架构设计,提升代码结构的可维护性与扩展性。 二、服务端模块设计目标 高内聚低耦合:各模块职责清晰,便于独立开发…...
【 java 虚拟机知识 第一篇 】
目录 1.内存模型 1.1.JVM内存模型的介绍 1.2.堆和栈的区别 1.3.栈的存储细节 1.4.堆的部分 1.5.程序计数器的作用 1.6.方法区的内容 1.7.字符串池 1.8.引用类型 1.9.内存泄漏与内存溢出 1.10.会出现内存溢出的结构 1.内存模型 1.1.JVM内存模型的介绍 内存模型主要分…...
【Pandas】pandas DataFrame dropna
Pandas2.2 DataFrame Missing data handling 方法描述DataFrame.fillna([value, method, axis, …])用于填充 DataFrame 中的缺失值(NaN)DataFrame.backfill(*[, axis, inplace, …])用于**使用后向填充(即“下一个有效观测值”)…...
大模型智能体核心技术:CoT与ReAct深度解析
**导读:**在当今AI技术快速发展的背景下,大模型的推理能力和可解释性成为业界关注的焦点。本文深入解析了两项核心技术:CoT(思维链)和ReAct(推理与行动),这两种方法正在重新定义大模…...

