Net Core 使用Mongodb操作文件(上传,下载)
Net Core 使用Mongodb操作文件(上传,下载)
1.Mongodb GridFS 文件操作帮助类。
GridFS 介绍 https://baike.baidu.com/item/GridFS/6342715?fr=aladdin
DLL源码:https://gitee.com/chenjianhua1985/mongodb-client-encapsulation
DLL文件:链接:https://pan.baidu.com/s/1SpWDtaXjavalJQav89UE4A?pwd=yceu 提取码:yceu
/// <summary>/// MongoDB 文件 操作类/// </summary>public abstract class MongoFileRepository : IMongoFileRepository{#region GridFS 介绍// MongodB使用两个集合来存储GridFS文件,一个是fs.files,另一个是fs.chunks// fs.files这个集合中存储的是每一个上传到数据库的文档的信息// fs.chunks这个集合存储的是上传文件的内容。一个chunk相当于一个文档(大文件被拆分成多个有序的chunk)// GridFS中的bucket这个概念指代的是fs.files和fs.chunks的组合// 它的工作原理是:// 在GridFS存储文件是将文件分块存储,文件会按照256KB的大小分割成多个块进行存储// GridFS使用两个集合// (collection)存储文件,一个集合是chunks, 用于存储文件的二进制数据// 一个集合是files,用于存储文件的元数据信息(文件名称、块大小、上传时间等信息)// 从GridFS中读取文件要对文件的各各块进行组装、合并// GridFSBucket 用于打开下载流对象#endregion/// <summary>/// 库 名/// </summary>public abstract string DataBaseName { get; }/// <summary>/// 配置类型/// </summary>public virtual DBConfigTypeEnum DBConfigType { get; set; } = DBConfigTypeEnum.WriteDB;/// <summary>/// 根据 Id 获取内部信息/// </summary>/// <param name="id"></param>/// <returns></returns>public ObjectId GetInternalId(string id){if (!ObjectId.TryParse(id, out ObjectId internalId))internalId = ObjectId.Empty;return internalId;}/// <summary>/// 根据 Id 获取文件 -- 异步/// </summary>/// <param name="id"></param>/// <returns></returns>public async Task<GridFSFileInfo> GetFileById(string id){// 通过系统 Id 筛选出包含 _id 的文件数据var filter = Builders<GridFSFileInfo>.Filter.Eq("_id", GetInternalId(id));return await MongoDBClient.GetGridFSBucketInstance(DataBaseName, DBConfigType).Find(filter).FirstOrDefaultAsync();}/// <summary>/// 根据 Id 获取文件 -- 异步/// </summary>/// <param name="id">文件Id</param>/// <returns></returns>public async Task<GridFSFileInfo> GetFileById(ObjectId id){var filter = Builders<GridFSFileInfo>.Filter.Eq("_id", id);return await MongoDBClient.GetGridFSBucketInstance(DataBaseName, DBConfigType).Find(filter).FirstOrDefaultAsync();}/// <summary>/// 上传文件 -- 异步/// </summary>/// <param name="fileName">文件名称</param>/// <param name="source">流</param>/// <returns></returns>public async Task<ObjectId> UploadFile(string fileName, Stream source){var id = await MongoDBClient.GetGridFSBucketInstance(DataBaseName, DBConfigType).UploadFromStreamAsync(fileName, source);return id;}/// <summary>/// 根据Id 下载文件流可搜索 -- 异步/// </summary>/// <param name="id"></param>/// <returns></returns>public async Task<GridFSDownloadStream<ObjectId>> DownloadFileStreamSeekable(string id){var options = new GridFSDownloadOptions{Seekable = true};return await MongoDBClient.GetGridFSBucketInstance(DataBaseName, DBConfigType).OpenDownloadStreamAsync(GetInternalId(id), options);}/// <summary>/// 根据Id 下载文件流可搜索 -- 异步/// </summary>/// <param name="id"></param>/// <returns></returns>public async Task<GridFSDownloadStream<ObjectId>> DownloadFileStreamSeekable(ObjectId id){var options = new GridFSDownloadOptions{Seekable = true};return await MongoDBClient.GetGridFSBucketInstance(DataBaseName, DBConfigType).OpenDownloadStreamAsync(id, options);}/// <summary>/// 根据 Id 下载文件流 -- 异步/// </summary>/// <param name="id"></param>/// <returns></returns>public async Task<GridFSDownloadStream<ObjectId>> DownloadFileStream(string id){return await MongoDBClient.GetGridFSBucketInstance(DataBaseName, DBConfigType).OpenDownloadStreamAsync(GetInternalId(id));}/// <summary>/// 下载 Id 获取文件流 -- 异步/// </summary>/// <param name="id"></param>/// <returns></returns>public async Task<GridFSDownloadStream<ObjectId>> DownloadFileStream(ObjectId id){return await MongoDBClient.GetGridFSBucketInstance(DataBaseName, DBConfigType).OpenDownloadStreamAsync(id);}/// <summary>/// 根据Id删除文件 -- 异步/// </summary>/// <param name="id"></param>/// <returns></returns>public async Task DeleteFile(string id){await MongoDBClient.GetGridFSBucketInstance(DataBaseName, DBConfigType).DeleteAsync(GetInternalId(id));}/// <summary>/// 根据Id删除文件 -- 异步/// </summary>/// <param name="id"></param>/// <returns></returns>public async Task DeleteFile(ObjectId id){await MongoDBClient.GetGridFSBucketInstance(DataBaseName, DBConfigType).DeleteAsync(id);}/// <summary>/// 根据Id和文件名称移除文件 -- 异步/// </summary>/// <param name="id"></param>/// <param name="newFilename"></param>/// <returns></returns>public async Task RenameFile(string id, string newFilename){await MongoDBClient.GetGridFSBucketInstance(DataBaseName, DBConfigType).RenameAsync(GetInternalId(id), newFilename);}/// <summary>/// 根据Id和文件名称移除文件 --异步/// </summary>/// <param name="id"></param>/// <param name="newFilename"></param>/// <returns></returns>public async Task RenameFile(ObjectId id, string newFilename){await MongoDBClient.GetGridFSBucketInstance(DataBaseName, DBConfigType).RenameAsync(id, newFilename);}}
在项目的使用实例
本人比较喜欢封装好再用。所以将上面的帮助类封装成了一个DLL文件,这样在项目中可以直接引用。
项目结构
API层有一个mongoDBConfig.json这个是客户端连接配置文件。
[{"DbName": "PMFiles","ReadConnectionString": "mongodb://192.168.10.200:27017","WriteConnectionString": "mongodb://192.168.10.200:27017"},{"DbName": "Test","ReadConnectionString": "mongodb://192.168.10.200:27017","WriteConnectionString": "mongodb://192.168.10.200:27017"}
]
使用很简单,在要引用的类库中直接引用DLL文件就可以。
下面是具体的实例代码:
1.数据访问层
/// <summary>/// MongodbFile处理接口/// </summary>public interface IFileRepository : IMongoFileRepository{}
这里创建的接口是空的,没有要扩展的方法,常用的接口都在 IMongoFileRepository 基类接口中定义了.
实现类:
/// <summary>/// Mongodb 文件 数据库 操作类/// </summary>public class FileRepository : MongoFileRepository , IFileRepository{public override string DataBaseName => "PMFiles";}
这里创建的实现类也是空的,没有要扩展的方法,常用的接口都在 MongoFileRepository基类中实现了.
注意: 这里重写了DataBaseName这里一定要重写基类的数据库名称。
2.业务层
/// <summary>/// 文件 操作 业务逻辑层接口/// </summary>public interface IFileService : IMongoFileRepository{}
实现类
这里主要是调用数据访问层的实例来实现功能。
[AutoInject(typeof(IFileService), InjectType.Scope)]
这里的服务注入用的是自动注入。可以改成手动注册。手动注册时可以删除类上的 AutoInject 标签
/// <summary>/// 文件操作服务/// </summary>[AutoInject(typeof(IFileService), InjectType.Scope)]public class FileService : IFileService{private readonly IFileRepository _srviceFile = RepositoryIocFactory.GetRegisterImp<IFileRepository>();public Task DeleteFile(string id){return _srviceFile.DeleteFile(id);}public Task DeleteFile(ObjectId id){return _srviceFile.DeleteFile(id);}public Task<GridFSDownloadStream<ObjectId>> DownloadFileStream(string id){return _srviceFile.DownloadFileStream(id);}public Task<GridFSDownloadStream<ObjectId>> DownloadFileStream(ObjectId id){return _srviceFile.DownloadFileStream(id);}public Task<GridFSDownloadStream<ObjectId>> DownloadFileStreamSeekable(string id){return _srviceFile.DownloadFileStreamSeekable(id);}public Task<GridFSDownloadStream<ObjectId>> DownloadFileStreamSeekable(ObjectId id){return _srviceFile.DownloadFileStreamSeekable(id);}public Task<GridFSFileInfo> GetFileById(string id){return _srviceFile.GetFileById(id);}public Task<GridFSFileInfo> GetFileById(ObjectId id){return _srviceFile.GetFileById(id);}public ObjectId GetInternalId(string id){return _srviceFile.GetInternalId(id);}public Task RenameFile(string id, string newFilename){return _srviceFile.RenameFile(id, newFilename);}public Task RenameFile(ObjectId id, string newFilename){return _srviceFile.RenameFile(id, newFilename);}public Task<ObjectId> UploadFile(string fileName, Stream source){return _srviceFile.UploadFile(fileName, source);}}
1、API层的实现
AIP层主要的接口有 上传 和 根据ID下载文件,以文件流对象返回数据。
/// <summary>/// MongoDB文件上传/// </summary>public class FileUploadController : BaseApiController{private IFileService serviceFile;public FileUploadController(IFileService fileService){serviceFile = fileService;}/// <summary>/// 上传文件/// </summary>/// <returns></returns>[HttpPost, Route("UploadFileAsync")][DisableRequestSizeLimit][DisableFormValueModelBinding]public async Task<AjaxResultPageModel> UploadFileAsync(){var rspModel = new AjaxResultPageModel();var fileIds = new List<string>();//检查ContentTypeif (!MultipartRequestHelper.IsMultipartContentType(Request.ContentType)){rspModel.Warning("内容类型不能为空");}else{var _defaultFormOptions = new FormOptions();var boundary = MultipartRequestHelper.GetBoundary(MediaTypeHeaderValue.Parse(Request.ContentType), _defaultFormOptions.MultipartBoundaryLengthLimit);var reader = new MultipartReader(boundary, Request.Body);var section = await reader.ReadNextSectionAsync();while (section != null){//把Form的栏位內容逐一取出var hasContentDispositionHeader = ContentDispositionHeaderValue.TryParse(section.ContentDisposition, out ContentDispositionHeaderValue contentDisposition);if (hasContentDispositionHeader){//按文件和键值对分类处理if (MultipartRequestHelper.HasFileContentDisposition(contentDisposition)){FileMultipartSection currentFile = section.AsFileSection();//存储文件到Mongovar id = await serviceFile.UploadFile(currentFile.FileName, section.Body);fileIds.Add(id.ToString());}}section = await reader.ReadNextSectionAsync();}rspModel.Success(fileIds);}return rspModel;}/// <summary>/// 下载文件/// </summary>[HttpGet,Route("Download")]public async Task<IActionResult> Download(string id){var fileInfo = await serviceFile.GetFileById(id);if (fileInfo == null){return NotFound();}else{return File(await serviceFile.DownloadFileStream(fileInfo.Id), "application/octet-stream", fileInfo.Filename);}}}
前端实现:
前端使用vue组件
<template><div class="home"><el-card class="box-card-top" shadow="never"><el-row :gutter="100"><el-col :span="2"><div class="user-avatar"><p class="user-avatar-text">{{ avatar }}</p></div></el-col><el-col :span="22"><div class="text"><h3>{{ holler }} {{ username }}</h3><p>桂树青春百里疆,鹧鸪啼彻午阴凉. 延平津上峰如削,剑去江空水自长.--剑道·尘心</p><p>活在当下,着眼未来.没有一往无前的觉悟.就不配握紧手中的双刀.空有大志,却没有实际行动.天下万般兵刃.唯有过往,伤人最深.如果真相带来痛苦.谎言只会雪上加霜. --LOL·亚索</p></div></el-col></el-row><!-- <h2>首页界面</h2><div class="hello"> --><!-- <el-input v-model="user" type="text" /> --><!-- <div id="message" v-html="remsg"></div> --><!-- <div id="el-input"><el-input id="chatbox" @keyup.native.enter="handle" type="textarea" :rows="1" placeholder="请输入内容" v-model="msg"></el-input></div><el-button size="small" style="display:inline-block;" icon="el-icon-s-promotion" type="suceess" @click="handle" plain></el-button> --><!-- </div> --></el-card><el-row :gutter="20"><el-col :span="4"><el-card class="box-card-center" shadow="never"><el-upload:action="action":file-list="modeList1":http-request="modeUpload1":multiple="true":before-remove="handleRemove1"><el-button size="small" type="primary">上传</el-button></el-upload><el-button @click="upload1">点击上传文件</el-button><br/><el-button @click="fileUpload">点击上传文件1</el-button></el-card></el-col><el-col :span="4"><el-card class="box-card-center" shadow="never"></el-card></el-col><el-col :span="4"><el-card class="box-card-center" shadow="never"></el-card></el-col></el-row></div></template><script>import axios from 'axios'import config from "../../config/index";import service from "../../api/UploadFiles/index";export default {data() {return {username: null,holler: "欢迎回来 — ",avatar: "",action: "", //上传文件的接口mode1: {},modeList1:[],fd1: new FormData()};},created() {this.username = JSON.parse(sessionStorage.getItem(config.localStorageKey)).userName;this.avatar = this.username.slice(0, 1);},methods: {modeUpload1: function(item) {// console.log(item.file);// this.mode1 = item.file// const isIMG =// item.file.type === 'image/jpg' ||// item.file.type === 'image/jpeg' ||// item.file.type === 'image/png'// const isLt = item.file.size / 1024 / 2000 <= 1// if (!isIMG) {// this.error='文件格式有误\n请上传后缀为jpg\\png的图片'// }// if (!isLt) {// // console.log(file.size)// this.error='上传头像图片大小不能超过500KB!'// }// if(isIMG&&isLt){this.fd1.append('files', item.file); //这里是自己把文件对象获取到,并存储起来//console.log("modeUpload1-> addFile:",item.file);//}},upload1: function() {console.log("upload1-> 11,files.length=",this.fd1.getAll('files').length);if(this.fd1.getAll('files').length===0){//formdata.getAll()返回的是一个file的数组(当然这里是你之前的参数得是文件)this.error='请先上传文件'}else {console.log("upload1-> post");axios.post('https://localhost:5001/adminapi/FileUpload/UploadFileAsync', this.fd1, { //headers: {'Content-Type': 'multipart/form-data'}}).then(response => {console.log("upload1->",response.data);})}},handleRemove1(file, fileList) {let files = this.fd1.getAll('files');this.fd1.delete('files');let len = files.lengthfor(var i=0;i<len;i++){if(files[i].uid!=file.uid){ //uid应该是可以唯一标志文件的,如果不能,就是我,会死this.fd1.append('files',files[i])}}},//上传方法fileUpload(uploader) {//let form = new FormData();//form.append("files", uploader.file);//console.log(this.fd1);//console.log("--------------------------");//console.log(uploader)service.uploadFlie(this.fd1// onUploadProgress: (progressEvent) => {// //这一步是展示上传的进度条,不展示也行,根据自身需求决定// let percent = ((progressEvent.loaded / progressEvent.total) * 100) | 0;// uploader.onProgress({ percent: percent }); //调用uploader的进度回调// },).then((res) => {console.log(res);if (res.success) {this.$message({message: "上传成功",type: "success",});} else {this.$message.error("上传失败,"+res.message);}}).catch((err) => {this.$message.error(err);});},},};/* import * as signalR from "@microsoft/signalr";let hubUrl = "https://localhost:44360/chatHub";//"https://localhost:44367/chatHub";//https://localhost:44318/chatHub; https://localhost:44367/chatHub//.net core 版本中默认不会自动重连,需手动调用 withAutomaticReconnectconst connection = new signalR.HubConnectionBuilder().withAutomaticReconnect().withUrl(hubUrl).build();connection.start().catch(err => alert(err.message));export default {name: "Im",mounted() {var _this = this;console.log('hubUrl:',hubUrl);//实现Show方法 OKconnection.on("Show", function(username, message) {_this.remsg = _this.remsg + "<br>" + username + ":" + message;console.log('Show:',message);});//实现ConnectResponse方法//connection.on("ChatHubReceiveMsg", function(username, message) {// _this.remsg = _this.remsg + "<br>" + username + ":" + message;// console.log('ChatHubReceiveMsg:',message);//}); //实现DisconnectResponse方法//connection.on("DisconnectResponse", function(username, message) {// _this.remsg = _this.remsg + "<br>" + username + ":" + message;// console.log('DisconnectResponse:',message);//});},data() {return {user: "cjh",msg: "",remsg: ""};},methods: {handle: function() {if(this.msg.trim()==""){alert("不能发送空白消息");return;}//调用后端方法 SendMsg 传入参数 OKconnection.invoke("SendMsg", this.user, this.msg);//connection.invoke("PublicSendMsg", this.msg);this.msg = "";}}}; */</script><style lang="less" scoped>.home {margin: 20px;.box-card-top {min-height: 160px;.user-avatar {width: 100px;height: 100px;margin-left: 50px;margin-top: 5px;border-radius: 50%;background-image: linear-gradient(#cdeefa, #b4b4fc);// background-color: #b4b4fc;.user-avatar-text {font-size: 40px;text-align: center;padding-top: 22px;color: #383838;}}.text h3 {margin-top: 20px;margin-bottom: 10px;font-size: 20px;}.text p {font-size: 16px;user-select: none;}}.box-card-center {width: 350px;height: 300px;margin-top: 20px;}}h1,h2 {font-weight: normal;}ul {list-style-type: none;padding: 0;}li {display: inline-block;margin: 0 10px;}a {color: #42b983;}#el-input {display: inline-block;width: 96%;float: left;}#message {overflow-y: auto;text-align: left;border: #42b983 solid 1px;height: 500px;}</style>
跨域问题处理。
requestFile.js
注意上图的类型只能是这个类型,只能一个类型,不能多。
//interceptors.js// vue axios配置 发起请求加载loading请求结束关闭loading
// http request 请求拦截器,有token值则配置上token值
import axios from 'axios'
import common from '../utils/common'
// import { API_BASE } from '../config/config';
// axios.defaults.baseURL = API_BASE;
// api base_url,设置前缀不存在
// const BASE_URL="";
const service = axios.create({baseURL: '', timeout: 60000, // 请求超时时间headers: {// Authorization: Authorization,'Content-Type': 'multipart/form-data'}
});
// Content-Type: application/wasmsql-wasm.wasm
// http请求拦截器
service.interceptors.request.use(config => {let token = common.getToken();//console.log('token:', token);if (token) {// bus.$emit('toggleloading', true)//显示loading// Loading.service(options);//如果token存在config.headers['Authorization'] = `Bearer ${token}`;//console.log('token 1:', token);}return config;},error => {Promise.reject(error);}
)// http response 服务器响应拦截器,
// 这里拦截401错误,并重新跳入登页重新获取token
service.interceptors.response.use(response => {if (response.status === 200) {//通讯成功// Toast.clear();// console.log(response);/************** response.data.status === 0 错误* response.data.status === 100 成功* response.data.status === 401 token过期** *************/// response.data.head.errorCode// bus.$emit('toggleloading', false)//隐藏loadingif (response.data.state == 401) {//未授权//如果是token过期,跳转至登录// console.log("401");//common.goLogin();message.error("未授权 请联系管理员!");//store.commit('setToken', '');} else if (response.data.state == 0) {// Message.error(response.data.message);return response.data;} else {// util.goLogin();return response.data;}}},error => {//请求失败// ;const response = error.response;if (response.status === 401) {// Toast.fail(response.data.message);message.error("未授权 请联系管理员!");//util.goLogin();} else if (response.status === 403) {$router.push({name: '403'});} else {// Toast.fail(response.data.message ? response.data.message : '系统错误请联系管理员');// message.error({// message: '无服务,请联系管理员'// });}return Promise.reject(error);}
);export default service;
API js
import http from '../../utils/http'export default {// 上传文件uploadFileAsync:(params) => {return http.postMongoDBFile("adminapi/FileUpload/UploadFileAsync",params);},// 下载文件download:(params) => {return http.postMongoDBdownloadFile("adminapi/FileUpload/Download?id="+params)}
};
完成。
END
相关文章:

Net Core 使用Mongodb操作文件(上传,下载)
Net Core 使用Mongodb操作文件(上传,下载) 1.Mongodb GridFS 文件操作帮助类。 GridFS 介绍 https://baike.baidu.com/item/GridFS/6342715?fraladdin DLL源码:https://gitee.com/chenjianhua1985/mongodb-client-encapsulati…...

适用于系统版本:CentOS 6/7/8的基线安全检测脚本
#!/bin/bash #适用于系统版本:CentOS 6/7/8 echo "----------------检测是否符合密码复杂度要求----------------" #把minlen(密码最小长度)设置为8-32位,把minclass(至少包含小写字母、大写字母、数字、特殊…...

Seata源码流程图
1.第一阶段分支事务的注册 流程图地址:https://www.processon.com/view/link/6108de4be401fd6714ba761d 2.第一阶段开启全局事务 流程图地址:https://www.processon.com/view/link/6108de13e0b34d3e35b8e4ef 3.第二阶段全局事务的提交 流程图地址…...

英飞凌电源管理PMIC的安全应用
摘要 本篇文档主要用来介绍英飞凌电源管理芯片TLF35584的使用,基于电动助力转向应用来介绍。包含一些安全机制的执行。 TLF35584介绍 TLF35584是英飞凌推出的针对车辆安全应用的电源管理芯片,符合ASIL D安全等级要求,具有高效多电源输出通道&…...
快速在Linux系统安装MySQL
虚拟机使用docker安装MySQL 使用docker拉去镜像 查看mysql的镜像 docker search mysql拉去mysql镜像 docker pull mysql查看下载的镜像 docker images启动容器 docker start mysql进入MySQL容器 docker exec -it mysql /bin/bash登录mysql mysql -u root -p检查是否进入…...
数据库相关理论知识(有目录便于直接锁定相关知识点+期末复习)
一,数据模型,关系型数据模型,网状模型,层次模型 1.数据库模型是用来描述和表示现实世界中的事物、概念以及它们之间的关系的工具,但是并不是越专业越好,还要平衡它的模型的复杂性、通用性和成本效益等因素…...
NCC环境配置
一、后端配置 1.安装eclipse汉化插件 2.安装svn插件...
用python实现Dubins曲线生成
Dubins曲线是连接两个具有指定方向和位置的点的最短路径,其中路径受到固定曲率约束(如车辆的转向限制)。Dubins曲线常用于机器人路径规划、车辆轨迹规划等领域。 Dubins曲线可以分为三种类型:CCC (Curve-Curve-Curve), CCL (Curv…...
智能技术上的“是”并不代表具体领域的“应该”
技术上的“是”并不代表具体领域的“应该” 。技术上的“是”仅仅是指某种方法或技术在实践中是否可行或有效,而不涉及是否该采取这种方法或技术。决定是否采取某种方法或技术还需要考虑伦理、法律、可行性等其他方面的因素。技术的发展可能会有各种可能性ÿ…...

永热爱 敢向前 | Paraverse平行云的2023 年终总结
永热爱,敢向前 值此新年,回顾2023,仅以此句,献给所有XR产业信仰者 2023 年,是XR产业技术和场景承上启下的关键之年 在这场波澜壮阔的技术潮中 「Paraverse平行云」踏浪前行 已是第八个年头,让我们一起…...
c/c++的内存分配,详细说一下栈、堆和静态存储区
栈区(Stack):由编译器自动分配和回收,栈中存放函数调用的相关信息,栈帧(记录函数的栈帧开始的位置),参数,局部变量,返回地址。其操作方法类似于数据结构中的栈…...
每日构造题训练——C. Divan and bitwise operations
每日构造题训练 题目链接: 题目传送门 前置知识: 按位或运算 一、题意: 1 1 1、 有一个长度为 n n n的但是元素未知的数组 a a a, 给定 m m m个约束,每个约束都有 l , r , x l, r, x l,r,x, 并且满足 1 ≤ l ≤ r ≤ n , 1 ≤ x < 2 30 , a [ l ] ∣ a [ l 1 …...

【C++练级之路】【Lv.13】多态(你真的了解虚函数和虚函数表吗?)
快乐的流畅:个人主页 个人专栏:《C语言》《数据结构世界》《进击的C》 远方有一堆篝火,在为久候之人燃烧! 文章目录 一、虚函数与重写1.1 虚函数1.2 虚函数的重写1.3 重写的特例1.4 final和override(C11)1.…...

如何在Windows系统安装Node.js环境并制作html页面发布公网远程访问?
文章目录 前言1.安装Node.js环境2.创建node.js服务3. 访问node.js 服务4.内网穿透4.1 安装配置cpolar内网穿透4.2 创建隧道映射本地端口 5.固定公网地址 前言 Node.js 是能够在服务器端运行 JavaScript 的开放源代码、跨平台运行环境。Node.js 由 OpenJS Foundation࿰…...

C#,数值计算,希尔伯特矩阵(Hilbert Matrix)的算法与源代码
Hilbert, David (1862-1943) 1 希尔伯特(Hilbert) 德国数学家,在《几何学基础》中提出了第一套严格的几何公理(1899年)。他还证明了自己的系统是自洽的。他发明了一条简单的空间填充曲线,即埃里克魏斯汀的数学世界,即希尔伯特曲线,埃里克魏斯汀的数学世界,并证明了不…...

【C++教程从0到1入门编程】第八篇:STL中string类的模拟实现
一、 string类的模拟实现 下面是一个列子 #include <iostream> namespace y {class string{public: //string() //无参构造函数// :_str(nullptr)//{}//string(char* str) //有参构造函数// :_str(str)//{}string():_str(new char[1]){_str[0] \0;}string(c…...

学生时期学习资源同步-1 第一学期结业考试题6
原创作者:田超凡(程序员田宝宝) 版权所有,引用请注明原作者,严禁复制转载...

迁移学习怎么用
如果想实现一个计算机视觉应用,而不想从零开始训练权重,比方从随机初始化开始训练,更快的方式是下载已经训练好权重的网络结构,把这个作为预训练,迁移到你感兴趣的新任务上。ImageNet、PASCAL等等数据库已经公开在线。…...

医疗手持智能终端读取条码二维码的难点有哪些?
在医疗科技行业信息化的大潮中,医疗手持式智能终端的应用越发普及,医疗手持式智能终端对条码二维码技术应用显得尤为关键,作为信息朔源载体的条码二维码读取方面,在实际应用中却面临着诸多问题,我们该如何应对…...

Python小设计
1. 五个PPT上的界面打印【print、input函数】 (1)英雄商城登陆界面 print(英雄联盟商城登录界面 ~ * ~ * ~ * ~ * ~ * ~ * ~ * ~ * ~ * ~ * ~ * ~ * ~ * ~ * ~1. 用户登录2. 新用户注册3. 退出系统 ~ * ~ * ~ * ~ * ~ * ~ * ~ * ~ * ~ * ~ * ~ * ~ * ~…...
web vue 项目 Docker化部署
Web 项目 Docker 化部署详细教程 目录 Web 项目 Docker 化部署概述Dockerfile 详解 构建阶段生产阶段 构建和运行 Docker 镜像 1. Web 项目 Docker 化部署概述 Docker 化部署的主要步骤分为以下几个阶段: 构建阶段(Build Stage):…...

【OSG学习笔记】Day 18: 碰撞检测与物理交互
物理引擎(Physics Engine) 物理引擎 是一种通过计算机模拟物理规律(如力学、碰撞、重力、流体动力学等)的软件工具或库。 它的核心目标是在虚拟环境中逼真地模拟物体的运动和交互,广泛应用于 游戏开发、动画制作、虚…...

基于距离变化能量开销动态调整的WSN低功耗拓扑控制开销算法matlab仿真
目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.算法仿真参数 5.算法理论概述 6.参考文献 7.完整程序 1.程序功能描述 通过动态调整节点通信的能量开销,平衡网络负载,延长WSN生命周期。具体通过建立基于距离的能量消耗模型&am…...

AI Agent与Agentic AI:原理、应用、挑战与未来展望
文章目录 一、引言二、AI Agent与Agentic AI的兴起2.1 技术契机与生态成熟2.2 Agent的定义与特征2.3 Agent的发展历程 三、AI Agent的核心技术栈解密3.1 感知模块代码示例:使用Python和OpenCV进行图像识别 3.2 认知与决策模块代码示例:使用OpenAI GPT-3进…...

关于iview组件中使用 table , 绑定序号分页后序号从1开始的解决方案
问题描述:iview使用table 中type: "index",分页之后 ,索引还是从1开始,试过绑定后台返回数据的id, 这种方法可行,就是后台返回数据的每个页面id都不完全是按照从1开始的升序,因此百度了下,找到了…...

【论文阅读28】-CNN-BiLSTM-Attention-(2024)
本文把滑坡位移序列拆开、筛优质因子,再用 CNN-BiLSTM-Attention 来动态预测每个子序列,最后重构出总位移,预测效果超越传统模型。 文章目录 1 引言2 方法2.1 位移时间序列加性模型2.2 变分模态分解 (VMD) 具体步骤2.3.1 样本熵(S…...

图表类系列各种样式PPT模版分享
图标图表系列PPT模版,柱状图PPT模版,线状图PPT模版,折线图PPT模版,饼状图PPT模版,雷达图PPT模版,树状图PPT模版 图表类系列各种样式PPT模版分享:图表系列PPT模板https://pan.quark.cn/s/20d40aa…...
Java多线程实现之Thread类深度解析
Java多线程实现之Thread类深度解析 一、多线程基础概念1.1 什么是线程1.2 多线程的优势1.3 Java多线程模型 二、Thread类的基本结构与构造函数2.1 Thread类的继承关系2.2 构造函数 三、创建和启动线程3.1 继承Thread类创建线程3.2 实现Runnable接口创建线程 四、Thread类的核心…...
代码随想录刷题day30
1、零钱兑换II 给你一个整数数组 coins 表示不同面额的硬币,另给一个整数 amount 表示总金额。 请你计算并返回可以凑成总金额的硬币组合数。如果任何硬币组合都无法凑出总金额,返回 0 。 假设每一种面额的硬币有无限个。 题目数据保证结果符合 32 位带…...

Golang——9、反射和文件操作
反射和文件操作 1、反射1.1、reflect.TypeOf()获取任意值的类型对象1.2、reflect.ValueOf()1.3、结构体反射 2、文件操作2.1、os.Open()打开文件2.2、方式一:使用Read()读取文件2.3、方式二:bufio读取文件2.4、方式三:os.ReadFile读取2.5、写…...