【超级详细】Vue3项目上传文件到七牛云的详细笔记
概述
继上一篇笔记介绍如何绑定七牛云的域名之后,这篇笔记主要介绍了如何在Vue3项目中实现文件上传至七牛云的功能。我们将使用Cropper.js来处理图像裁剪,并通过自定义组件和API调用来完成整个流程。
这里直接给出关键部分js代码,上传之前要先获取一个上传凭证,这里是由后端接口生成的具体的实现代码在后文有体现,这里实现的功能逻辑为:将上传的图片转化为base64数据之后调用uploadToQiniu 方法。
uploadToQiniu 方法实现为:
- 将base64的数据解码出数据类型或直接使用默认类型
- 调用父组件的props.nickname设置文件名称这一步可以自定义实现
- 调用useFileApi().upload() 接口获取上传凭证以及空间域名用于拼接图片访问url
- 将base64数据转为二进制数据
- 动态导入qiniu-js (PS:这里用动态导入的原因是直接导入会导致父组件加载子组件的时候出现问题)
- 调用Qiniu.upload方法上传文件
- 跟踪上传进度这里用一个message弹框直接显示
const uploadToQiniu = async (base64Image) => {// 提取Base64编码中的图片类型const base64Data = base64Image.split(',')[0];const typeMatch = base64Data.match(/data:(.+);base64,/);const type = typeMatch ? typeMatch[1] : 'jpg';const nickname = (props.nickname || '匿名用户').replace(/[\\/:*?"<>|]/g, '').trim().substring(0, 50);const fileName = `${nickname}-avatar-${Date.now()}.${ type }`;const result = await useFileApi().upload(fileName);if (!result || !result.data) {ElMessage.error('未能获取上传凭证');return;}const { token, domain } = result.data;// 将base64转换为二进制数据const base64 = base64Image.split(',')[1];const byteCharacters = atob(base64);const byteNumbers = new Array(byteCharacters.length);for (let i = 0; i < byteCharacters.length; i++) {byteNumbers[i] = byteCharacters.charCodeAt(i);}const byteArray = new Uint8Array(byteNumbers);const file = new File([byteArray], fileName, { type: type });// 动态导入qiniu-jsconst Qiniu = await import("qiniu-js");const config = {useCdnDomain: true,region: 'z2',domain: domain, //配置好的七牛云域名chunkSize: 100, //每个分片的大小,单位mb,默认值3forceDirect: true //直传还是断点续传方式,true为直传};const putExtra = {fname: '',params: {},mimeType: type,};let uploadMessage = null; // 用于跟踪进度消息return new Promise((resolve, reject) => {const observable = Qiniu.upload(file, fileName, token, putExtra, config);const observer = {next(res) {if (uploadMessage === null) { // 确保只显示一次进度消息uploadMessage = ElMessage({message: '上传中...',duration: 0,type: 'success',onClose: () => {uploadMessage = null;}});}// 更新消息内容以显示进度,这里假设res.total === 100表示100%if (res.total === 100) {uploadMessage.close();}},error(err) {if (uploadMessage) {uploadMessage.close(); // 关闭进度消息}ElMessage.error('上传失败: ' + err.message);reject(err);},complete(res) {if (res.key) {if (uploadMessage) {uploadMessage.close();}resolve(`http://${domain}/${res.key}`);} else {if (uploadMessage) {uploadMessage.close();}reject(new Error('上传成功,但未获取到文件key或域名'));}},};observable.subscribe(observer);});
};
下面是一个完整的前后端部分代码
技术栈
- 前端框架: Vue3
- 状态管理: Pinia
- UI库: Element Plus
- 图像裁剪工具: Cropper.js
- 后端语言: Python (FastAPI)
- 存储服务: 七牛云
实现步骤
1. 安装依赖
首先,确保你已经安装了必要的npm包:
npm install cropperjs element-plus pinia qiniu-js
2. 创建用户信息组件
创建一个名为Personal.vue
的组件,用于展示和编辑用户信息。
前端代码比较多这里这展示关键部分js代码 源码在文末
<!-- 设置头像组件 通过updateAvatar传递到父组件 通过nickname传递到子组件 -->
<SeePictures ref="SeePicturesRef"@updateAvatar="updateAvatar":nickname="state.personalForm.nickname"
></SeePictures>const SeePictures = defineAsyncComponent(() => import("/@/components/seePictures/index.vue"))
const SeePicturesRef = ref();// 打开裁剪弹窗
const onCropperDialogOpen = () => {nextTick(() => {SeePicturesRef.value.openDialog(state.personalForm.avatar);});
};
const save = async () => {// 保存用户信息await useUserApi().saveOrUpdate(state.personalForm)await getUserInfo()ElMessage.success("更新成功!╰(*°▽°*)╯😍")if (state.showEditPage){state.showEditPage = !state.showEditPage}
}
const updateAvatar = async (img) => {state.personalForm.avatar = img// 跟新session中用户信息await userStores.updateAvatar(img)save()
}
3. 创建图片查看与裁剪组件
创建一个名为SeePictures.vue
的组件,用于显示和裁剪图片。
前端代码比较多这里这展示关键部分js代码 源码在文末
const onSubmit = async () => {state.cropperImgBase64 = state.cropper.getCroppedCanvas().toDataURL('image/jpeg');try {const qiniuResult = await uploadToQiniu(state.cropperImgBase64);if (qiniuResult) {emit("updateAvatar", qiniuResult);closeDialog();}} catch (error) {console.error('上传到七牛云失败:', error);}// emit("updateAvatar", state.cropperImgBase64)// closeDialog();
};// 上传到七牛云
const uploadToQiniu = async (base64Image) => {// 提取Base64编码中的图片类型const base64Data = base64Image.split(',')[0];const typeMatch = base64Data.match(/data:(.+);base64,/);const type = typeMatch ? typeMatch[1] : 'jpg';const nickname = (props.nickname || '匿名用户').replace(/[\\/:*?"<>|]/g, '').trim().substring(0, 50);const fileName = `${nickname}-avatar-${Date.now()}.${ type }`;const result = await useFileApi().upload(fileName);if (!result || !result.data) {ElMessage.error('未能获取上传凭证');return;}const { token, domain } = result.data;// 将base64转换为二进制数据const base64 = base64Image.split(',')[1];const byteCharacters = atob(base64);const byteNumbers = new Array(byteCharacters.length);for (let i = 0; i < byteCharacters.length; i++) {byteNumbers[i] = byteCharacters.charCodeAt(i);}const byteArray = new Uint8Array(byteNumbers);const file = new File([byteArray], fileName, { type: type });// 动态导入qiniu-jsconst Qiniu = await import("qiniu-js");const config = {useCdnDomain: true,region: 'z2',domain: domain, //配置好的七牛云域名chunkSize: 100, //每个分片的大小,单位mb,默认值3forceDirect: true //直传还是断点续传方式,true为直传};const putExtra = {fname: '',params: {},mimeType: type,};let uploadMessage = null; // 用于跟踪进度消息return new Promise((resolve, reject) => {const observable = Qiniu.upload(file, fileName, token, putExtra, config);const observer = {next(res) {if (uploadMessage === null) { // 确保只显示一次进度消息uploadMessage = ElMessage({message: '上传中...',duration: 0,type: 'success',onClose: () => {uploadMessage = null;}});}// 更新消息内容以显示进度,这里假设res.total === 100表示100%if (res.total === 100) {uploadMessage.close();}},error(err) {if (uploadMessage) {uploadMessage.close(); // 关闭进度消息}ElMessage.error('上传失败: ' + err.message);reject(err);},complete(res) {if (res.key) {if (uploadMessage) {uploadMessage.close();}resolve(`http://${domain}/${res.key}`);} else {if (uploadMessage) {uploadMessage.close();}reject(new Error('上传成功,但未获取到文件key或域名'));}},};observable.subscribe(observer);});
};
4. 前端接口代码
在你的API模块中添加上传文件的方法。
import request from '/@/utils/request';/*** 文件接口*/
export function useFileApi() {return {upload: (data) => {return request({url: '/file/qiniu/token',method: 'POST',data,});}};
}
5. 后端接口代码
编写FastAPI后端接口以获取七牛云上传凭证并处理文件上传。
@router.post('/qiniu/token', description="获取文件上传凭证")
async def upload(file_name: str = Body(...)):result = await FileService.upload(file_name)return partner_success(result)
class FileService:@staticmethodasync def upload(file_name: str) -> dict:""" 生成七牛云上传凭证 """try:logger.info(f'生成七牛云上传凭证....')result = upload_file(file_name)logger.info(f"七牛云上传凭证生成成功--> {result['token'][:12] + '*'*20}")return resultexcept Exception as e:logger.error(f'七牛云上传凭证生成失败: {e}')raise ParameterError(CodeEnum.FILE_UPLOAD_FAILED)
# 上传文件类
class UploadQiNiu:# 仅支持单文件上传def __init__(self, config):self.access_key = config['access_key']self.secret_key = config['secret_key']self.bucket_name = config['bucket_name']self.domain = config['domain']self._q = Auth(self.access_key, self.secret_key)self._bucket = BucketManager(self._q)def get_qiniu_upload_token(self, save_file_name):""" 获取七牛云上传凭证 """return self._q.upload_token(self.bucket_name, save_file_name)
""" 七牛云配置 """
qiniu_config = {'access_key': config.access_key, # access_key'secret_key': config.secret_key, # secret_key'bucket_name': config.bucket_name, # 存储空间名称'domain': config.domain # 空间域名
}# 获取七牛云上传凭证
def upload_file(save_file_name: str) -> dict:try:upload_qiniu = UploadQiNiu(qiniu_config)token = upload_qiniu.get_qiniu_upload_token(save_file_name)return {'token': token,'domain': qiniu_config['domain']}except Exception as e:logger.warning(f'获取七牛云上传凭证失败: {e}')raise ParameterError(CodeEnum.FILE_UPLOAD_FAILED)
Personal.vue 组件代码
<template><div><!-- 设置头像组件 --><SeePictures ref="SeePicturesRef" @updateAvatar="updateAvatar" :nickname="state.personalForm.nickname"></SeePictures><!-- 其他表单项 --><el-form label-width="100px"><el-form-item label="用户名"><el-input v-model="state.personalForm.username" disabled></el-input></el-form-item><el-form-item label="昵称"><el-input v-model="state.personalForm.nickname"></el-input></el-form-item><el-form-item label="邮箱"><el-input v-model="state.personalForm.email"></el-input></el-form-item><el-form-item label="标签"><el-tag v-for="(tag, index) in state.personalForm.tags" :key="index" closable @close="removeTag(tag)">{{ tag }}</el-tag><el-input v-if="state.editTag" ref="UserTagInputRef" v-model="state.tagValue" size="small" style="width: 100px;"@keyup.enter.native="addTag" @blur="addTag"></el-input><el-button v-else class="button-new-tag ml-1" size="small" @click="showEditTag">+ New Tag</el-button></el-form-item><el-form-item><el-button type="primary" @click="save">保存</el-button></el-form-item></el-form></div>
</template><script setup name="personal">
import { defineAsyncComponent, nextTick, onMounted, reactive, ref } from 'vue';
import { useUserInfo } from "/@/stores/userInfo";
import { useUserApi } from "/@/api/useSystemApi/user";
import { ElMessage } from "element-plus";
import { storeToRefs } from "pinia";const SeePictures = defineAsyncComponent(() => import("/@/components/seePictures/index.vue"));
const SeePicturesRef = ref();
const UserTagInputRef = ref();// 用户信息
const userStores = useUserInfo();
const { userInfos } = storeToRefs(userStores);// 定义变量内容
const state = reactive({personalForm: {username: '',nickname: '',avatar: '',email: '',tags: '',},editTag: false,tagValue: "",cropperImg: '',
});const getUserInfo = async () => {let { data } = await useUserApi().getUserInfoByToken();if (!data.avatar) {data.avatar = "";}state.personalForm = data;
};// 打开裁剪弹窗
const onCropperDialogOpen = () => {nextTick(() => {SeePicturesRef.value.openDialog(state.personalForm.avatar);});
};// tags
const showEditTag = () => {state.editTag = true;nextTick(() => {UserTagInputRef.value?.input.focus();});
};const removeTag = (tag) => {state.personalForm.tags.splice(state.personalForm.tags.indexOf(tag), 1);
};const addTag = () => {if (state.editTag && state.tagValue) {if (!state.personalForm.tags) state.personalForm.tags = [];state.personalForm.tags.push(state.tagValue);}state.editTag = false;state.tagValue = '';
};const save = async () => {// 保存用户信息await useUserApi().saveOrUpdate(state.personalForm);await getUserInfo();ElMessage.success("更新成功!╰(*°▽°*)╯😍");
};const updateAvatar = async (img) => {state.personalForm.avatar = img;// 更新session中用户信息await userStores.updateAvatar(img);save();
};onMounted(() => {getUserInfo();
});
</script><style scoped>
.button-new-tag {margin-left: 10px;height: 32px;line-height: 30px;padding-top: 0;padding-bottom: 0;
}
</style>
<template><div><el-dialog title="裁剪图片" v-model="dialogVisible" width="80%"><div class="cropper-content"><img id="image" :src="imageUrl" alt="Source Image" /></div><template #footer><span class="dialog-footer"><el-button @click="dialogVisible = false">取消</el-button><el-button type="primary" @click="cropImage">确定</el-button></span></template></el-dialog></div>
</template><script setup>
import { ref, watch } from 'vue';
import Cropper from 'cropperjs';
import 'cropperjs/dist/cropper.min.css';const props = defineProps({nickname: String,
});const emit = defineEmits(['updateAvatar']);let imageUrl = ref('');
let dialogVisible = ref(false);
let cropper = null;watch(dialogVisible, (val) => {if (!val) {cropper.destroy();}
});const openDialog = (url) => {imageUrl.value = url;dialogVisible.value = true;nextTick(() => {cropper = new Cropper(document.getElementById('image'), {aspectRatio: 1 / 1,viewMode: 1,autoCropArea: 1,cropBoxResizable: false,});});
};const cropImage = () => {cropper.getCroppedCanvas().toBlob(async (blob) => {const formData = new FormData();formData.append('file', blob, `${props.nickname}_avatar.png`);try {const response = await fetch('/file/qiniu/upload', {method: 'POST',body: formData,});const result = await response.json();emit('updateAvatar', result.url);} catch (error) {console.error(error);}}, 'image/png');
};
</script><style scoped>
.cropper-content {max-height: 50vh;overflow-y: auto;
}#image {display: block;width: 100%;
}
</style>
总结
通过以上步骤,我们实现了从Vue3前端发起请求、获取七牛云上传凭证、上传文件到七牛云的过程。整个过程包括了用户信息展示、图片裁剪、文件上传等功能,适用于大多数需要文件上传功能的场景。
相关文章:
【超级详细】Vue3项目上传文件到七牛云的详细笔记
概述 继上一篇笔记介绍如何绑定七牛云的域名之后,这篇笔记主要介绍了如何在Vue3项目中实现文件上传至七牛云的功能。我们将使用Cropper.js来处理图像裁剪,并通过自定义组件和API调用来完成整个流程。 这里直接给出关键部分js代码,上传之前要先…...
设计模式-建造者模式
在面向对象的设计中,建造者模式(Builder Pattern) 是一种常用的设计模式,它属于创建型模式,旨在将复杂对象的创建与其表示分离。通过该模式,我们可以一步一步地构造一个复杂的对象,避免构造函数…...
springboot+vue实现SSE服务器发送事件
思路 一个基于订阅发布机制的SSE事件。客户端可以请求订阅api(携带客户端id),与服务器建立SSE链接;后续服务器需要推送消息到客户端时,再根据客户端id从已建立链接的会话中找到目标客户端,将消息推送出去。…...
IDEA | SpringBoot 项目中使用 Apifox 上传接口
目录 1 安装 Apifox Helper 插件2 获取 Apifox 的 API 访问令牌3 IDEA 中设置 API 访问令牌4 IDEA 中上传接口5 常见问题5.1 如何自动设置目录名5.2 如何自动设置接口名5.3 如何更改上传位置 Apifox 官方指南: https://apifox.com/help/applications-and-p…...
SpringBoot基础二
扩展SpringBoot 扩展SpringBoot中的SpringMVC的默认配置 SpringBoot默认已经给我们做了很多SpringMVC的配置,哪些配置? 1、视图解析器ViewResolver 2、静态资料的目录 3、默认首页index.html 4、图标名字和图标所在目录,favicon.ico 5、类型转…...
力扣第129题:求根到叶子节点数字之和 - C语言解法
力扣第129题:求根到叶子节点数字之和 - C语言解法 题目描述 给定一个二叉树,求根到叶子节点的数字之和。 每条从根到叶子的路径都代表一个数字。例如,根到叶子路径 1->2->3 代表数字 123。返回所有路径数字之和。 示例 1࿱…...
图像处理-Ch7-小波函数
个人博客!无广告观看,因为这节内容太多了,有点放不下,分了三节 文章目录 多分辨率展开(Multi-resolution Expansions)序列展开(Series Expansions)尺度函数(Scaling Function)例:哈尔尺度函数(Haar scaling func)多分…...
Unity中实现转盘抽奖效果(一)
实现思路: 旋转转盘的z轴,开始以角加速度加速到角速度最大值,结束的时候,以角加速度减速使角速度减少到0,然后转盘z轴旋转的角度就是加上每秒以角速度数值大小,为了使角度不能一直增大,对360度…...
小程序基础 —— 07 创建小程序项目
创建小程序项目 打开微信开发者工具,左侧选择小程序,点击 号即可新建项目: 在弹出的新页面,填写项目信息(后端服务选择不使用云服务,开发模式为小程序,模板选择为不使用模板)&…...
Apache Commons Pool :介绍与使用
Apache Commons Pool :介绍与使用 什么是 commons-pool2? commons-pool2 是 Apache Commons 提供的一个开源对象池实现框架。它旨在为应用程序提供通用的对象池支持,方便开发者管理资源(如数据库连接、网络连接等)复…...
(二)编译原生SDK以及配置交叉编译链
文章目录 编译原生SDKLinuxSDK的安装第一步解压LinuxSDK第二步安装依赖软件第三步解压Buildroot的dl文件 Linux系统镜像编译、生成第一步 配置编译环境第二步 编译 LinuxSDK编译上面配置好的 环境配置编译 LinuxSDK配置内核选项配置 Buildroot编译 Qt 库 编译生成 Linux 系统镜…...
YK人工智能(三)——万字长文学会torch深度学习
2.1 张量 本节主要内容: 张量的简介PyTorch如何创建张量PyTorch中张量的操作PyTorch中张量的广播机制 2.1.1 简介 几何代数中定义的张量是基于向量和矩阵的推广,比如我们可以将标量视为零阶张量,矢量可以视为一阶张量,矩阵就是…...
【游戏设计原理】41 - 游戏的核心
1. 如何理解? 这条原理主要在讲述“游戏核心”这一概念的重要性及其在游戏开发中的作用。游戏的核心是指决定游戏整体玩法和体验的核心元素,它通常是游戏的主要机制、目标或动作方式。理解这一原理时,我们可以从以下几个层面来考虑ÿ…...
GraalVM:云原生时代的Java虚拟机
1. 概述 GraalVM是由Oracle公司开发的一款高性能、多语言的虚拟机平台。它不仅兼容传统的JVM字节码执行,还引入了即时编译(JIT)技术的革新,以及对多种编程语言的支持。GraalVM旨在通过提供更高效的执行环境来满足云计算环境中日益…...
goView二开低代码平台1.0
官网文档地址:GoView 说明文档 | 低代码数据可视化开发平台 简介:GoView 是一个拖拽式低代码数据可视化开发平台,通过拖拽创建数据大屏,使用Vue3框架,Ts语言和NaiveUI组件库创建的开源项目。安装步骤和地址文档里都有…...
【golang】go errors 处理错误追踪打印堆栈信息
目录 背景使用参考 背景 使用原生go语言编程时,常常需要处理错误,然而golang中没有像java/python等其他语言的try-catch方式一样的方式来处理异常事件,只能通过函数返回值接收并处理错误。 在实践中,由于牛马的不熟练或随意处理错…...
【brew安装失败】DNS 查询 raw.githubusercontent.com 返回的是 0.0.0.0
从你提供的 nslookup 输出看,DNS 查询 raw.githubusercontent.com 返回的是 0.0.0.0,这通常意味着无法解析该域名或该域名被某些 DNS 屏蔽了。这种情况通常有几个可能的原因: 可能的原因和解决方法 本地 DNS 问题: 有可能是你的本…...
【Python系列】Python 连接 PostgreSQL 数据库并查询数据
💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…...
深度学习利用Kaggle和Colab免费GPU资源训练
这两个平台,我先用的Colab,在修改完无数bug,成功训练完一个epoch后,超时了,查阅了官网资料,之后应该还可以用,但这个限制是动态的,你可能第二天就可以用,也没准下个月。遂…...
WebAssembly 学习笔记
WASM 概述 wasm最初是为了在浏览器获得接近原生的性能体验。 支持将其他语言实现的程序编译到wasm字节码,引入到浏览器由JS交互调用。 后又有了脱离JS的wasm运行时,可以直接运行wasm。 从而促成了wasm跨平台分发的能力。 但由于运行时的安全沙箱限制&a…...
二、github基础
Github基础 备用github.com网站一、用户界面-Overview(概览)1用户信息2 导航栏3 热门仓库4 贡献设置5贡献活动6搜索和筛选7自定义收藏8贡献统计9最近活动10其他链接 二、用户界面-Repositories(仓库)1 libusb_stm322 savedata3 Fi…...
「下载」智慧文旅运营综合平台解决方案:整体架构,核心功能设计
智慧文旅运营综合平台,旨在通过集成大数据、云计算、物联网、人工智能等先进技术,为景区、旅游企业及相关管理机构提供一站式的智慧化运营服务。 智慧文旅运营综合平台不仅能够提升游客的游览体验,还能帮助景区管理者实现资源的优化配置和业务…...
《探寻真正开源的大模型:开启AI创新新纪元》
《探寻真正开源的大模型:开启AI创新新纪元》 一、开源大模型崛起:AI 发展的新曙光二、开源大模型的 “庐山真面目”三、明星开源大模型闪耀登场(一)LLaMA 3:实力强劲的开源先锋(二)Phi-3&#x…...
麒麟信安云在长沙某银行的应用入选“云建设与应用领航计划(2024)”,打造湖湘金融云化升级优质范本
12月26日,2024云计算产业和标准应用大会在北京成功召开。大会汇集政产学研用各方专家学者,共同探讨云计算产业发展方向和未来机遇,展示云计算标准化工作重要成果。 会上,云建设与应用领航计划(2024)建云用…...
C#如何操作数据库
C#如何操作数据库 前言1、查询操作2、增删改操作3、需要返回id主键的sql语句执行 前言 本文主要交代如何通过引用 using MySql.Data.MySqlClient;来操作数据库 需要导入.dll文件 例如:在本地Mysql下载目录下->Connecter NET 8.0->Assemblies->net5.0->…...
c++领域展开第八幕——类和对象(下篇 初始化列表、类型转换、static成员)超详细!!!!
文章目录 前言一、初始化列表二、类型转换三、static成员总结 前言 上篇博客我们实现了一个简单的日期类,基本的类和对象是清楚了 今天我们再来学习后面的一些类和对象的语法,慢慢的完善所学的东西 fellow me 一、初始化列表 • 之前我们实现构造函数时…...
termux-boot安卓开机自动启动应用
termux安装 github 蓝奏云 v119.1 termux-boot安装 github 蓝奏云 v0.8.1 安装 给权限运行加锁后台 am启动应用命令 am start -n 包名/启动项获取包名和启动入口(图中app为爱玩机工具箱) 例 简黑时钟蓝奏云 包名com.hm.jhclock 桌面启动项com.hm.jh…...
Echart实现3D饼图示例
在可视化项目中,很多地方会遇见图表;echart是最常见的;这个示例就是用Echart, echart-gl实现3D饼图效果,复制即可用 //需要安装,再引用依赖import * as echarts from "echarts"; import echar…...
【JAVA】神经网络的基本结构和前向传播算法
前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默, 忍不住分享一下给大家。点击跳转到网站 学习总结 1、掌握 JAVA入门到进阶知识(持续写作中……) 2、学会Oracle数据库入门到入土用法(创作中……) 3、手把…...
设计模式-抽象工厂模式
在设计模式中,抽象工厂模式(Abstract Factory Pattern)是一个非常常见且重要的模式,它属于创建型模式,用于提供创建一组相关或相互依赖对象的接口,而无需指定具体类。它的核心思想是将“创建对象”这一功能…...
webpack
前言 在现代前端开发的浪潮中,Webpack 已经成为一个不可或缺的构建工具。它不仅能够帮助我们打包 JavaScript 代码,还能够处理各种资源(如 CSS、图片、字体等),并提供一系列优化手段,极大地提升开发效率和…...
BLIP论文笔记
论文地址 BLIP: Bootstrapping Language-Image Pre-training for Unified Vision-Language Understanding and Generation 论文思想 其实Clip就相当于只用了ITC...
Java List 集合详解:基础用法、常见实现类与高频面试题解析
正文 在 Java 集合框架中,List 是一个非常重要的接口,广泛用于存储有序的元素集合。本文将带你深入了解 List 接口的基本用法、常见实现类及其扩展,同时通过实际代码示例帮助你快速掌握这些知识。 👉点击获取2024Java学习资料 1…...
HTML5 SSE
HTML5 SSE(Server-Sent Events,服务器发送事件)是一种允许服务器实时向浏览器推送数据的技术。它是HTML5规范的一部分,主要通过HTTP协议实现。SSE的主要特点包括: 单向通信:与WebSocket不同,SSE…...
SpringBoot篇(监控)
目录 学习前言 一、什么是监控? 二、监控的意义 1. 简介 2. 总结 3. 思考 三、可视化监控平台 1. 简介 2. 实操 2.1. 服务端开发 2.2. 客户端开发 配置多个客户端 2.3. 总结 2.4. 思考 四、监控原理 1. 简介 2. 总结 五、自定义监控指标 1. 简介…...
python23-常用的第三方库01:request模块-爬虫
requests 模块是 Python 中的一个第三方库,用于发送 HTTP 请求。 它提供了一个简单且直观的 API,使得发送网络请求和解析响应变得非常容易。requests 模块支持各种 HTTP 方法,如 GET、POST、PUT、DELETE 等,并且具有处理 cookies…...
【pytorch】现代卷积神经网络
文章目录 1 AlexNet2 VGG3 NiN4 GoogLeNet5 批量规范化batch normalization6 ResNet6.1 残差块6.2 resnet 7 DenseNet7.1 稠密块体7.2 过渡层7.3 DenseNet模型 1 AlexNet AlexNet由八层组成:五个卷积层、两个全连接隐藏层和一个全连接输出层。 AlexNet使用ReLU而不…...
Excel 身份证号计算年龄
1. 设置身份证号列格式 复制身份证列值到记事本或其他地方重新设置身份证号列单元格格式为“文本”将复制出去的身份证号重新复制粘贴回来 2. 年龄列单元格中添加公式 DATEDIF(DATE(LEFT(MID(A2, 7, 8), 4), MID(MID(A2, 7, 8), 5, 2), RIGHT(MID(A2, 7, 8), 2)), TODAY(), …...
【ArcGIS Pro】完整的nc文件整理表格模型构建流程及工具练习数据分享
学术科研啥的要用到很多数据,nc文件融合了时间空间数据是科研重要文件。之前分享过怎样将nc文件处理成栅格后整理成表格。小编的读者还是有跑不通整个流程的,再来做一篇总结篇,也分享下练习数据跟工具,如果还是弄不了的࿰…...
WebRTC的线程模型
WebRTC中的线程类: Thread类: (1)Thread类中的数据: class Thread {// 消息队列:MessageList messages_; // 消息队列,所有需要线程处理的消息,都要先入队PriorityQueue delayed_m…...
活动预告 | Microsoft Power Platform 在线技术公开课:实现业务流程自动化
课程介绍 参加“Microsoft Power Platform 在线技术公开课:实现业务流程自动化”活动,了解如何更高效地开展业务。参加我们举办的本次免费培训活动,了解如何借助 Microsoft AI Builder 和 Power Automate 优化工作流。结合使用这些工具可以帮…...
Docker安装(Docker Engine安装)
一、Docker Engine和Desktop区别 Docker Engine 核心组件:Docker Engine是Docker的核心运行时引擎,负责构建、运行和管理容器。它包括守护进程(dockerd)、API和命令行工具客户端(docker)。适用环境&#…...
Spring自动化创建脚本-解放繁琐的初始化配置!!!(自动化SSM整合)
一、实现功能(原创,转载请告知) 1.自动配置pom配置文件 2.自动识别数据库及数据表,创建Entity、Dao、Service、Controller等 3.自动创建database.properties、mybatis-config.xml等数据库文件 4.自动创建spring-dao.xml spring-mvc.xml …...
Llama系列关键知识总结
系列文章目录 第一章:LoRA微调系列笔记 第二章:Llama系列关键知识总结 第三章:LLaVA模型讲解与总结 文章目录 系列文章目录Llama: Open and Efficient Foundation Language Models关键要点LLaMa模型架构:Llama2分组查询注意力 (G…...
分布式系统架构6:链路追踪
这是小卷对分布式系统架构学习的第6篇文章,关于链路追踪,之前写过traceId的相关内容:https://juejin.cn/post/7135611432808218661,不过之前写的太浅了,且不成系统,只是简单的理解,今天来捋一下…...
flink cdc使用flink sql方式运行一直报Make sure a planner module is on the classpath
flink cdc使用flink sql方式运行一直报Make sure a planner module is on the classpath 引入jar包信息: flink-connector-oracle-cdc:3.2.1 flink:1.20.0 flink-table-runtime:1.20.0 flink-streaming-java:1.20.0 flink-clients:1.20.0 Exception in thread &q…...
Vue.js组件开发-怎样将style私有化
Vue.js组件开发中,将style私有可以通过使用<style scoped>来实现的。scoped属性会告诉Vue为这个组件的CSS样式添加一个数据属性,从而确保这些样式只应用于该组件的元素,而不会影响到其他组件或全局样式。 示例: 展示如何使…...
第十届“挑战杯”大学生课外学术科技作品竞赛解析及资料
“挑战杯”被誉为大学生科技创新创业的“奥林匹克”盛会,它汇聚了来自各个学科、各个年级的精英人才。在这里,同学们带着对未知的好奇和对知识的渴望,组成一个个团队,向难题发起挑战。现在,第十届“挑战杯”大学生课外…...
从0入门自主空中机器人-2-1【无人机硬件框架】
关于本课程: 本次课程是一套面向对自主空中机器人感兴趣的学生、爱好者、相关从业人员的免费课程,包含了从硬件组装、机载电脑环境设置、代码部署、实机实验等全套详细流程,带你从0开始,组装属于自己的自主无人机,并让…...
跟着逻辑先生学习FPGA-实战篇第一课 6-1 LED灯闪烁实验
硬件平台:征战Pro开发板 软件平台:Vivado2018.3 仿真软件:Modelsim10.6d 文本编译器:Notepad 征战Pro开发板资料 链接:https://pan.baidu.com/s/1AIcnaGBpNLgFT8GG1yC-cA?pwdx3u8 提取码:x3u8 1 知识背景 LED,又名…...