上传图片到腾讯云和wangeditor的图片上传到腾讯云

news/2024/9/14 2:20:33/ 标签: 腾讯云, 云计算

1.创建src/utils/upload-file.js文件

import COS from 'cos-js-sdk-v5'
import SparkMD5 from 'spark-md5'
import { cosTmpsecret, cosConfig } from '@/api/upload' // 通过后台获取临时密钥
let key = ''
// 配置
// const cosConfig = {
//   // Bucket: 'xlcp-tong-1253334579',
//   // Region: 'ap-nanjing',
//   Bucket: 'mytong-1259414159',
//   Region: 'ap-nanjing',
//   // Domain: 'mytong-1259414159.cos.ap-nanjing.myqcloud.com'
// }
// 初始化实例
/*** 签名计算放在前端会暴露 SecretId 和 SecretKey* 我们把签名计算过程放在后端实现,前端通过 ajax 向后端获取签名结果* 正式部署时请再后端加一层自己网站本身的权限检验。* 异步获取临时密钥* mytong-1259414159.cos.ap-nanjing.myqcloud.com* mytong-1259414159* SecretKey:A3oKYrI2YrsfFX4LL3VgZBXu7HJETRCf* SecretId:AKIDrYy7VdZIqMaXVDQjaE7lFjGoAFJAmMgj* APPID:1259414159**/
let cos = new COS({async getAuthorization(options, callback) {const res = await cosTmpsecret()const authdata = res.dataconst auth = {TmpSecretId: authdata.tmpSecretId,TmpSecretKey: authdata.tmpSecretKey,XCosSecurityToken: authdata.sessionToken,StartTime: authdata.startTime,ExpiredTime: authdata.expiredTime, // 在ExpiredTime时间前,不会再次调用getAuthorization}callback(auth)},FileParallelLimit: 3, // 文件并发数ChunkParallelLimit: 8, // 同一个上传文件的分块并发数ChunkSize: 1024 * 1024 * 8, // 分块上传时,每块的字节数大小
})//   var cos1 = new COS({
//     SecretId: 'A3oKYrI2YrsfFX4LL3VgZBXu7HJETRCf',
//     SecretKey: 'AKIDrYy7VdZIqMaXVDQjaE7lFjGoAFJAmMgj',
//     FileParallelLimit: 3, // 文件并发数
//     ChunkParallelLimit: 8, // 同一个上传文件的分块并发数
//     ChunkSize: 1024 * 1024 * 8 // 分块上传时,每块的字节数大小
// });// 获取cos存储的图片地址,替换为域名地址
export async function getObjectUrl() {let response = await cosConfig()const url = cos.getObjectUrl({Bucket: response.data.bucket,Region: response.data.region,Key: key,Sign: false,}, (err, data) => {})return url// 腾讯云的地址替换为域名地址// const p = `${cosConfig.Bucket}.cos.${cosConfig.Region}.myqcloud.com`// console.log('p:', p)// console.log('url:', url)// .replace(p, cosConfig.Domain)
}
// 下载对象
export function getObject(path, url) {cosConfig().then(response => {console.log('response', response)let arr = url.split('.com')// console.log('arr', arr[1])cos.getObject({Bucket: response.data.bucket,Region: response.data.region,Key: arr[1], /* 必须 */}, (err, data) => {console.log(err || data.Body)})})
}
// 获得文件md5
function getFileMD5(file, callback) {// 声明必要的变量const fileReader = new FileReader()// 文件每块分割2M,计算分割详情const chunkSize = 2 * 1024 * 1024const chunks = Math.ceil(file.size / chunkSize)let currentChunk = 0// 创建md5对象(基于SparkMD5)const spark = new SparkMD5()// 每块文件读取完毕之后的处理fileReader.onload = function (e) {// 每块交由sparkMD5进行计算spark.appendBinary(e.target.result)currentChunk++// 如果文件处理完成计算MD5,如果还有分片继续处理if (currentChunk < chunks) {loadNext()} else {callback(spark.end())}}// 处理单片文件的上传function loadNext() {const start = currentChunk * chunkSizeconst end = start + chunkSize >= file.size ? file.size : start + chunkSizefileReader.readAsBinaryString(file.slice(start, end))}loadNext()
}
// 大文件分片上传-通过sliceUploadFile上传
export function uploadFile(path, file, callback, progressBc) {return new Promise(resolve => {cosConfig().then(response => {// 得到md5码getFileMD5(file, md5 => {// 存储文件的md5码file.md5 = md5const subfix = file.name.substr(file.name.lastIndexOf('.'))key = path + file.md5 + new Date().getSeconds() + subfixcos.sliceUploadFile({Bucket: response.data.bucket,Region: response.data.region,Key: key,Body: file,onProgress(progressData) {progressBc(progressData.percent)},}, async (err, data) => {if (err) {callback(err)resolve(err)} else {data.fid = await getObjectUrl()console.log(' data.fid1111111111', data)callback(null, data)resolve(data)}})})})})
}
// 小文件直接上传-通过putObject上传
export function uploadFile2(path, file, callback, progressBc) {// 得到md5码try {cosConfig().then(response => {getFileMD5(file, md5 => {// 存储文件的md5码file.md5 = md5const subfix = file.name.substr(file.name.lastIndexOf('.'))key = path + file.md5 + new Date().getSeconds() + subfixcos.putObject({Bucket: response.data.bucket,Region: response.data.region,Key: key,Body: file,onProgress(progressData) {progressBc(progressData.percent)},}, async (err, data) => {if (err) {callback(err)} else {data.fid = await getObjectUrl()console.log(' data.fid1111111111', data.fid)callback(null, data)}})})})} catch (error) {console.log(error)}
}
// 文件直接删除-通过deleteObject上传
export function deleteFile(path, file, callback, keyName) {cosConfig().then(response => {console.log('response', response)if (keyName) {let key = path + keyNamecos.deleteObject({Bucket: response.data.bucket,Region: response.data.region,Key: key,}, (err, data) => {if (err) {callback(err)} else {callback(null, data)}})} else {key = path + file.namecos.deleteObject({Bucket: response.data.bucket,Region: response.data.region,Key: key,}, (err, data) => {if (err) {callback(err)} else {callback(null, data)}})}})
}

2.在vue中上传图片使用

import { uploadFile2 } from '@/utils/upload-file'
import dayjs from 'dayjs'const { proxy } = getCurrentInstance()
function uploadImg({ file }) {const TODAY = dayjs().format('YYYY/MM/DD')uploadFile2(`/upload/company-products/${TODAY}/`, file, (err, datas) => {if (err) {number.value--proxy.$modal.closeLoading()proxy.$modal.msgError(datas.msg)proxy.$refs.imageUpload.handleRemove(file)uploadedSuccessfully()this.$message.error(`上传失败:${err}`)} else {uploadList.value.push({ name: datas.fid, url: datas.fid })uploadedSuccessfully()proxy.$modal.msgSuccess('上传成功!')}})
}// 上传结束处理
function uploadedSuccessfully() {if (number.value > 0 && uploadList.value.length === number.value) {fileList.value = fileList.value.filter((f) => f.url !== undefined).concat(uploadList.value)uploadList.value = []number.value = 0emit('update:modelValue', listToString(fileList.value))proxy.$modal.closeLoading()}
}

完整代码:

<template><div class="component-upload-image"><!-- :on-success="handleUploadSuccess" --><el-uploadmultipleaction="#":http-request="uploadImg"list-type="picture-card":before-upload="handleBeforeUpload":limit="limit":on-error="handleUploadError":on-exceed="handleExceed"ref="imageUpload":before-remove="handleDelete":show-file-list="true":headers="headers":file-list="fileList":on-preview="handlePictureCardPreview":class="{ hide: fileList.length >= limit }"><el-icon class="avatar-uploader-icon"><plus /></el-icon></el-upload><!-- 上传提示 --><div class="el-upload__tip" v-if="showTip">请上传<template v-if="fileSize">大小不超过 <b style="color: #f56c6c">{{ fileSize }}MB</b></template><template v-if="fileType">格式为 <b style="color: #f56c6c">{{ fileType.join('/') }}</b></template>的文件</div><el-dialogv-model="dialogVisible"title="预览"width="800px"append-to-body><img:src="dialogImageUrl"style="display: block; max-width: 100%; margin: 0 auto"/></el-dialog></div>
</template><script setup>
import { getToken } from '@/utils/auth'
import { uploadFile2 } from '@/utils/upload-file'
import dayjs from 'dayjs'const props = defineProps({modelValue: [String, Object, Array],// 图片数量限制limit: {type: Number,default: 5,},// 大小限制(MB)fileSize: {type: Number,default: 5,},// 文件类型, 例如['png', 'jpg', 'jpeg']fileType: {type: Array,default: () => ['png', 'jpg', 'jpeg'],},// 是否显示提示isShowTip: {type: Boolean,default: true,},
})const { proxy } = getCurrentInstance()
const emit = defineEmits()
const number = ref(0)
const uploadList = ref([])
const dialogImageUrl = ref('')
const dialogVisible = ref(false)
const baseUrl = import.meta.env.VITE_APP_BASE_API
const uploadImgUrl = ref(`${import.meta.env.VITE_APP_BASE_API}/common/upload`) // 上传的图片服务器地址
const headers = ref({ Authorization: `Bearer ${getToken()}` })
const fileList = ref([])
// const COSJS = ref(null)
const showTip = computed(() => props.isShowTip && (props.fileType || props.fileSize),
)watch(() => props.modelValue,(val) => {if (val) {// 首先将值转为数组const list = Array.isArray(val) ? val : props.modelValue.split(',')// 然后将数组转为对象数组fileList.value = list.map((item) => {if (typeof item === 'string') {if (item.indexOf(baseUrl) === -1) {item = { name: baseUrl + item, url: baseUrl + item }} else {item = { name: item, url: item }}}return item})} else {fileList.value = []return []}},{ deep: true, immediate: true },
)
function uploadImg({ file }) {console.log('uploadImg', file)const TODAY = dayjs().format('YYYY/MM/DD')uploadFile2(`/upload/company-products/${TODAY}/`, file, (err, datas) => {console.log(datas, 'datas')console.log(file, 'datas')if (err) {number.value--proxy.$modal.closeLoading()proxy.$modal.msgError(datas.msg)proxy.$refs.imageUpload.handleRemove(file)uploadedSuccessfully()this.$message.error(`上传失败:${err}`)} else {uploadList.value.push({ name: datas.fid, url: datas.fid })uploadedSuccessfully()proxy.$modal.msgSuccess('上传成功!')}})
}// 上传前loading加载
function handleBeforeUpload(file) {let isImg = falseif (props.fileType.length) {let fileExtension = ''if (file.name.lastIndexOf('.') > -1) {fileExtension = file.name.slice(file.name.lastIndexOf('.') + 1)}isImg = props.fileType.some((type) => {if (file.type.indexOf(type) > -1) return trueif (fileExtension && fileExtension.indexOf(type) > -1) return truereturn false})} else {isImg = file.type.indexOf('image') > -1}if (!isImg) {proxy.$modal.msgError(`文件格式不正确, 请上传${props.fileType.join('/')}图片格式文件!`,)return false}if (props.fileSize) {const isLt = file.size / 1024 / 1024 < props.fileSizeif (!isLt) {proxy.$modal.msgError(`上传头像图片大小不能超过 ${props.fileSize} MB!`)return false}}proxy.$modal.loading('正在上传图片,请稍候...')number.value++
}// 文件个数超出
function handleExceed() {proxy.$modal.msgError(`上传文件数量不能超过 ${props.limit} 个!`)
}// 上传成功回调
// function handleUploadSuccess(res, file) {
//   console.log(res, file, 'res, file')
//   if (res.code === 200) {
//     uploadList.value.push({ name: res.fileName, url: res.fileName })
//     uploadedSuccessfully()
//   } else {
//     number.value--
//     proxy.$modal.closeLoading()
//     proxy.$modal.msgError(res.msg)
//     proxy.$refs.imageUpload.handleRemove(file)
//     uploadedSuccessfully()
//   }
// }// 删除图片
function handleDelete(file) {const findex = fileList.value.map((f) => f.name).indexOf(file.name)if (findex > -1 && uploadList.value.length === number.value) {fileList.value.splice(findex, 1)emit('update:modelValue', listToString(fileList.value))return false}
}// 上传结束处理
function uploadedSuccessfully() {if (number.value > 0 && uploadList.value.length === number.value) {fileList.value = fileList.value.filter((f) => f.url !== undefined).concat(uploadList.value)uploadList.value = []number.value = 0emit('update:modelValue', listToString(fileList.value))proxy.$modal.closeLoading()}
}// 上传失败
function handleUploadError() {proxy.$modal.msgError('上传图片失败')proxy.$modal.closeLoading()
}// 预览
function handlePictureCardPreview(file) {dialogImageUrl.value = file.urldialogVisible.value = true
}// 对象转成指定字符串分隔
function listToString(list, separator) {let strs = ''separator = separator || ','for (let i in list) {if (undefined !== list[i].url && list[i].url.indexOf('blob:') !== 0) {strs += list[i].url.replace(baseUrl, '') + separator}}return strs != '' ? strs.substr(0, strs.length - 1) : ''
}
</script><style scoped lang="scss">
// .el-upload--picture-card 控制加号部分
:deep(.hide .el-upload--picture-card) {display: none;
}
</style>

3.在富文本使用

// 编辑器配置
const editorConfig = ref({placeholder: computed(() => props.placeholder),MENU_CONF: {uploadImage: {customUpload(file, insertFn) {console.log(file, insertFn, 'upload')const TODAY = dayjs().format('YYYY/MM/DD')uploadFile2(`/upload/company-products/${TODAY}/`, file, (err, data) => {console.log(data, 'datas')console.log(file, 'datas')if (err) {ElMessage({message: `${file.name} 上传失败`,type: 'error',})} else {// 成功后,调用插入图片的函数const imageUrl = `http://${data.Location}`console.log(data.Location, 'image')console.log(imageUrl, 'image')insertFn(imageUrl, '', '')}})},// server: () => {// },// form-data fieldName ,默认值 'wangeditor-uploaded-image'fieldName: 'file',// 单个文件的最大体积限制,默认为 2MmaxFileSize: 5 * 1024 * 1024, // 3M// 最多可上传几个文件,默认为 100maxNumberOfFiles: 10,// 选择文件时的类型限制,默认为 ['image/*'] 。如不想限制,则设置为 []allowedFileTypes: ['image/*'],// 自定义增加 http  headerheaders: {Authorization: `Bearer ${getToken()}`,},// 跨域是否传递 cookie ,默认为 falsewithCredentials: true,// 超时时间,默认为 10 秒timeout: 5 * 1000, // 5 秒// 上传失败onFailed(file) {ElMessage({message: `${file.name} 上传失败`,type: 'error',})},// 上传出错onError(file, err) {errorTips(err)},// 自定义插入customInsert(res, insertFn) {// 从 res 中找到 url alt href ,然后插入图片insertFn(res.url, '', '')},},uploadVideo: {server: `${import.meta.env.VITE_APP_BASE_API}/common/upload`,// form-data fieldName ,默认值 'wangeditor-uploaded-image'fieldName: 'file',// 单个文件的最大体积限制,默认为 2MmaxFileSize: 20 * 1024 * 1024, // 10M// 最多可上传几个文件,默认为 100maxNumberOfFiles: 10,// 选择文件时的类型限制,默认为 ['video/*'] 。如不想限制,则设置为 []allowedFileTypes: ['video/*'],// 自定义增加 http  headerheaders: {Authorization: `Bearer ${getToken()}`,},// 跨域是否传递 cookie ,默认为 falsewithCredentials: true,// 超时时间,默认为 10 秒timeout: 15 * 1000, // 5 秒// 上传失败onFailed(file) {ElMessage({message: `${file.name} 上传失败`,type: 'error',})},// 上传出错onError(file, err) {errorTips(err)},// 自定义插入customInsert(res, insertFn) {// 从 res 中找到 url alt href ,然后插入insertFn(res.url, '', '')},},},
})

完整代码:

<!--* @Description: wangEditor* @Author: ZhengQiang Zeng* @Date: 2023-05-17 14:53:37* @LastEditors: ZhengQiang Zeng* @LastEditTime: 2023-05-18 10:35:01
-->
<template><div style="border: 1px solid #ccc"><!-- 工具栏 --><Toolbar:editor="editorRef":defaultConfig="toolbarConfig"style="border-bottom: 1px solid #ccc"/><!-- 编辑器 --><Editorv-model="valueHtml":defaultConfig="editorConfig":style="`height: ${height}px; overflow-y: hidden`"@onCreated="handleCreated"/></div>
</template><script setup>
import { computed, onBeforeUnmount, ref, shallowRef } from 'vue'
// eslint-disable-next-line import/no-extraneous-dependencies
import { Editor, Toolbar } from '@wangeditor/editor-for-vue'
import { ElMessage } from 'element-plus'
import { getToken } from '@/utils/auth'
import { uploadFile2 } from '@/utils/upload-file'
import dayjs from 'dayjs'const props = defineProps({html: {type: String,default: '',},// 富文本高度height: {type: Number,default: 400,},// 是否为禁用状态disabled: {type: Boolean,default: false,},placeholder: {type: String,default: '请输入内容',},
})// 编辑器实例,必须用 shallowRef,重要!
const editorRef = shallowRef()// 内容 HTML
const valueHtml = ref()
watch(() => props.html,() => {valueHtml.value = props.html},
)// 工具栏配置
const toolbarConfig = ref({})// 编辑器配置
const editorConfig = ref({placeholder: computed(() => props.placeholder),MENU_CONF: {uploadImage: {customUpload(file, insertFn) {console.log(file, insertFn, 'upload')const TODAY = dayjs().format('YYYY/MM/DD')uploadFile2(`/upload/company-products/${TODAY}/`, file, (err, data) => {console.log(data, 'datas')console.log(file, 'datas')if (err) {ElMessage({message: `${file.name} 上传失败`,type: 'error',})} else {// 成功后,调用插入图片的函数const imageUrl = `http://${data.Location}`console.log(data.Location, 'image')console.log(imageUrl, 'image')insertFn(imageUrl, '', '')}})},// server: () => {// },// form-data fieldName ,默认值 'wangeditor-uploaded-image'fieldName: 'file',// 单个文件的最大体积限制,默认为 2MmaxFileSize: 5 * 1024 * 1024, // 3M// 最多可上传几个文件,默认为 100maxNumberOfFiles: 10,// 选择文件时的类型限制,默认为 ['image/*'] 。如不想限制,则设置为 []allowedFileTypes: ['image/*'],// 自定义增加 http  headerheaders: {Authorization: `Bearer ${getToken()}`,},// 跨域是否传递 cookie ,默认为 falsewithCredentials: true,// 超时时间,默认为 10 秒timeout: 5 * 1000, // 5 秒// 上传失败onFailed(file) {ElMessage({message: `${file.name} 上传失败`,type: 'error',})},// 上传出错onError(file, err) {errorTips(err)},// 自定义插入customInsert(res, insertFn) {// 从 res 中找到 url alt href ,然后插入图片insertFn(res.url, '', '')},},uploadVideo: {server: `${import.meta.env.VITE_APP_BASE_API}/common/upload`,// form-data fieldName ,默认值 'wangeditor-uploaded-image'fieldName: 'file',// 单个文件的最大体积限制,默认为 2MmaxFileSize: 20 * 1024 * 1024, // 10M// 最多可上传几个文件,默认为 100maxNumberOfFiles: 10,// 选择文件时的类型限制,默认为 ['video/*'] 。如不想限制,则设置为 []allowedFileTypes: ['video/*'],// 自定义增加 http  headerheaders: {Authorization: `Bearer ${getToken()}`,},// 跨域是否传递 cookie ,默认为 falsewithCredentials: true,// 超时时间,默认为 10 秒timeout: 15 * 1000, // 5 秒// 上传失败onFailed(file) {ElMessage({message: `${file.name} 上传失败`,type: 'error',})},// 上传出错onError(file, err) {errorTips(err)},// 自定义插入customInsert(res, insertFn) {// 从 res 中找到 url alt href ,然后插入insertFn(res.url, '', '')},},},
})function errorTips(err) {err = String(err)err = err.replace(/Error: /g, '错误:')err = err.replace(/exceeds maximum allowed size of/g,'超过了允许的最大上传大小',)ElMessage({message: `${err}`,type: 'error',})
}// 获取 HTML 内容
const getHtml = () => {const res = editorRef.value.getHtml()if (res !== '<p><br></p>') {return res}return ''
}// 暴露出去给父组件获取
defineExpose({getHtml,
})const handleCreated = (editor) => {editorRef.value = editor // 记录 editor 实例,重要!
}// 组件销毁时,及时销毁编辑器
onBeforeUnmount(() => {const editor = editorRef.valueif (editor == null) returneditor.destroy()
})
</script><!-- 引入样式 -->
<style src="@wangeditor/editor/dist/css/style.css"></style>


http://www.ppmy.cn/news/1475459.html

相关文章

WPF学习(6) -- WPF命令和通知

一 、WPF命令 1.ICommand代码 创建一个文件夹和文件 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Input;namespace 学习.Command {public class MyCommand : ICommand{Acti…

旅游景区度假村展示型网站如何建设渠道品牌

景区、度假村、境外旅游几乎每天的人流量都非常高&#xff0c;还包括本地附近游等&#xff0c;对景区及度假村等固定高流量场所&#xff0c;品牌和客户赋能都是需要完善的&#xff0c;尤其是信息展示方面&#xff0c;旅游客户了解前往及查看信息等。 通过雨科平台建设景区度假…

本地部署,APISR: 动漫超分辨率技术

目录 引言 技术背景 APISR 的架构与原理 APISR 的主要特点 应用实例 本地部署 运行结果 结论 参考文献 GitHub - Kiteretsu77/APISR: APISR: Anime Production Inspired Real-World Anime Super-Resolution (CVPR 2024)APISR: Anime Production Inspired Real-World A…

百川工作手机实现销售管理微信监控系统

在瞬息万变的商业战场中&#xff0c;每一分效率的提升都是企业制胜的关键。传统销售管理模式已难以满足现代企业对精准、高效、合规的迫切需求。今天&#xff0c;让我们一同探索如何利用工作手机这一创新工具&#xff0c;为您的销售团队装上智能翅膀&#xff0c;开启销售管理的…

MySQL Binlog详解:提升数据库可靠性的核心技术

文章目录 1. 引言1.1 什么是MySQL Bin Log&#xff1f;1.2 Bin Log的作用和应用场景 2. Bin Log的基本概念2.1 Bin Log的工作原理2.2 Bin Log的三种格式 3. 配置与管理Bin Log3.1 启用Bin Log3.2 配置Bin Log参数3.3 管理Bin Log文件3.4 查看Bin Log内容3.5 使用mysqlbinlog工具…

张量笔记(4):张量网络

张量分解通常是将高维张量分解成一系列较低维的张量&#xff0c;表示能力相对较低。而张量网络可以表示复杂的高维数据结构&#xff0c;通过连接多个张量形成网络结构&#xff0c;可以更灵活地表示和处理复杂的数据关系。本节主要介绍HT和TT网络。 2.5.1 HT分解——首先我们引入…

Mac OS ssh 连接提示 Permission denied (publickey)

这错误有点奇葩&#xff0c;MacBook的IDE(vscode和pycharm)远程都连不上&#xff0c;terminal能连上&#xff0c;windows的pycharm能连上&#xff0c;见鬼了&#xff0c;所以肯定不是秘钥的问题了&#xff0c;查了好久竟然发现是权限的问题。。 chmod 400 ~/.ssh/id_rsa http…

兼容问题---ios底部的安全距离css设置

在H5上适配安全区域&#xff1a;采用viewportenvconstant方案。 具体操作如下&#xff1a; 1. 需要将viewport设置为cover&#xff0c;env和constant才能生效。设置代码如下&#xff1a; <meta name"viewport" content"widthdevice-width,initial-scale1.…

设置Llinux自带的led功能,在timer模式下设置delay_on后会把delay_off给清0

记录&#xff1a; 内核版本4.9.88. 问题复现方法是&#xff1a; 1. cd /sys/class/leds/cpu //cpu是内核自带led的节点名 2. echo timer > trigger 3. echo 100 > delay_on在设置完delay_on之后&#xff0c;发现delay_off自己设置为0了。同理设置delay_off后&#xff…

无障碍快捷方式图标

问题背景 测试反馈&#xff0c;无障碍快捷方式和setting里的无障碍图标不一致。 无障碍快捷方式悬浮窗 1、悬浮窗在systemui中 frameworks\base\packages\SystemUI\src\com\android\systemui\accessibility\floatingmenu\AccessibilityTargetAdapter.java 图标获取方式&…

C#面:ABP.NEXT 是什么,请阐述 ?

ASP.NET Boilerplate是.Net平台⾮常优秀的⼀个开源Web应⽤程序框架,在国内也有⼤量的粉丝.从名称可以看出来, 这是ASP.NET Boilerplate的下⼀代框架。 ABP框架创作于2013年&#xff0c;那时候没有.Net Core和ASP.NET Core&#xff0c;也没有Angular2 。ABP发布后&#xff0c;它…

01、Kerberos安全认证之原理及搭建命令使用学习笔记

文章目录 前言一、Kerberos原理1.1、数据安全防护&#xff08;kerberos所属的层次&#xff09;1.2、Kerberos介绍1.3、Kerberos名词介绍1.4、Kerberos术语1.5、Kerberos认证流程1.5.1、Kerberos流程图1.5.2、第一次通信&#xff1a;客户端与AS1.5.3、第二次通信&#xff1a;客户…

DNF手游攻略:云手机辅助刷副本!内置辅助工具!

DNF手游是一款备受玩家喜爱的角色扮演类游戏&#xff0c;以其独特的地下城探险和多样化的装备系统而闻名。玩家需要通过不断的挑战和升级&#xff0c;逐步增强自己的角色实力&#xff0c;最终完成各种高难度的副本任务。游戏的核心玩法包括打怪、刷装备、升级技能等。 游戏辅助…

【JavaScript脚本宇宙】提升用户体验:探索 JavaScript 命令行界面开发工具

构建交互式命令行&#xff1a;JavaScript 中的 CLI 开发利器 前言 在现代软件开发中&#xff0c;命令行界面&#xff08;CLI&#xff09;和终端应用程序的开发变得越来越重要。为了提高用户体验和交互性&#xff0c;使用合适的工具和库是至关重要的。本文将介绍一些用于构建命…

基于Python进行分类算法实验(人工智能)的设计与实现

基于Python进行分类算法实验(人工智能)的设计与实现 “Design and Implementation of Python-based Classification Algorithm Experiment in Artificial Intelligence” 完整下载链接:基于Python进行分类算法实验(人工智能)的设计与实现 文章目录 基于Python进行分类算法实验…

数据建设实践之大数据平台(二)安装zookeeper

安装zookeeper 上传安装包到/opt/software目录并解压 [bigdatanode101 software]$ tar -zxvf apache-zookeeper-3.5.7-bin.tar.gz -C /opt/services/ 重命名文件 [bigdatanode101 services]$ mv apache-zookeeper-3.5.7-bin zookeeper-3.5.7 配置环境变量 export JAVA_H…

RabbitMq,通过prefetchCount限制消费并发数

1.问题:项目瓶颈,通过rabbitMq来异步上传图片,由于并发上传的图片过多导致阿里OSS异常, 解决方法:通过prefetchCount限制图片上传OSS的并发数量 2.定义消费者 Component AllArgsConstructor Slf4j public class ReceiveFaceImageEvent {private final UPloadService uploadSe…

ES索引模板

在Elasticsearch中&#xff0c;索引模板&#xff08;Index Templates&#xff09;是用来预定义新创建索引的设置和映射的一种机制。当你创建了一个索引模板&#xff0c;它会包含一系列的默认设置和映射规则&#xff0c;这些规则会在满足一定条件的新索引被创建时自动应用。 索…

使用 Azure DevOps Pipelines 生成 .NET Core WebJob 控制台应用 CI/CD

Web 应用程序通常需要作为后台任务运行的进程&#xff0c;并在特定时间间隔进行计划或在事件中触发。它们不需要花哨的 IO 接口&#xff0c;因为重点是过程而不是输出。Azure WebJobs 提供了出色的支持&#xff0c;通常在云环境中通过 Web 控制台应用程序来实现此目的。WebJob …

基于全国产复旦微JFM7K325T+ARM人工智能数据处理平台

复旦微可以配合的ARM平台有&#xff1a;RK3588/TI AM62X/ NXP IMX.8P/飞腾FT2000等。 产品概述 基于PCIE总线架构的高性能数据预处理FMC载板&#xff0c;板卡采用复旦微的JFM7K325T FPGA作为实时处理器&#xff0c;实现各个接口之间的互联。该板卡可以实现100%国产化。 板卡具…