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>();
            //检查ContentType
            if (!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();
                            //存储文件到Mongo
                            var 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.length
        for(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 版本中默认不会自动重连,需手动调用 withAutomaticReconnect
  const 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方法 OK
      connection.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 传入参数 OK
        connection.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)//隐藏loading
            if (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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

学习笔记-华为IPD转型2020:1,IPD的重要意义

华为产品开发转型&#xff1a;IPD计划 大多数公司发现&#xff0c;当公司大幅增长时&#xff0c;在较小规模上有效的管理实践不再有效。产品开发过程也是如此。随着华为的发展&#xff0c;该公司遇到了产品故障率更高、开发周期更长和研发成本增加等问题。然后&#xff0c;它转…

vulntarget-k - 内网渗透

标签 xxl-job rce Spring-Cloud-CVE-2022-22947 nacos auth bypass iox 靶机难度比较简单&#xff0c;都是用用 exp 就好了 拓扑图 网卡设置 首先需要使用虚拟网络编辑器&#xff0c;增加 VMnet1、VMnet2、VMnet3 对三张网卡设置子网 IP VMnet1 192.168.100.0 VMnet2 1…

BOOTMGR is missing 问题

同事一台win2k8的虚机在重启后无法引导开机&#xff0c;提示如下信息&#xff1a; 开始就觉得是引导分区设置错了。遂从网上下了一个winpe的镜像&#xff0c;装载到虚机“光驱”中&#xff0c;从光盘引导启动。打开“磁盘管理”后发现&#xff0c;果然&#xff0c;未安装系统…

【趣味学算法】03_兑换钱币

注&#xff1a; 本系列仅为个人学习笔记&#xff0c;学习内容为《算法小讲堂》&#xff08;视频传送门&#xff09;&#xff0c;通俗易懂适合编程入门小白&#xff0c;需要具备python语言基础&#xff0c;本人小白&#xff0c;如内容有误感谢您的批评指正 要将 50 元的软妹币兑…

LeetCode——贪心算法(Java)

贪心算法 简介[简单] 455. 分发饼干[中等] 376. 摆动序列[中等] 53. 最大子数组和[中等] 122. 买卖股票的最佳时机 II[中等] 55. 跳跃游戏 简介 记录一下自己刷题的历程以及代码。写题过程中参考了 代码随想录的刷题路线。会附上一些个人的思路&#xff0c;如果有错误&#xf…

SAP 读写生产订单长文本简介

通常在物料主数据,生产订单,采购订单中都会维护长文本的信息在业务数据中。但是我们在获取长文本的时候需要调用函数才能获取到对应业务数据的长文本的信息。 我们以获取生产订单中的长文本为例 首先需要获取到这个长文本的文本对象,文本名,文本标识 我们可以通过后台表S…

【知识库系统】使用SpringSecurity进行身份认证

一、理论知识部分 SpringSecurity 的官网文档地址&#xff1a;SpringSecurity 这里以24年3月份的 6.2.2 版本为例&#xff0c;记录一下学习过程。 1. SpringSecurity 是基于 Servlet Filters 的&#xff0c;而 Servlet Filters 中的流程如下&#xff1a;首先由客户端 Client…

[LeetCode][LCR 194]二叉树的最近公共祖先

题目 LCR 194. 二叉树的最近公共祖先 给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。 例如&#xff0c;给定如下二叉树: root [3,5,1,6,2,0,8,null,null,7,4] 示例 1: 输入: root [3,5,1,6,2,0,8,null,null,7,4], p 5, q 1 输出: 3 解释: 节点 5 和节点 1 的最…

数据库系统概念(第二周 第一堂)

前言 本文的所有知识点、图片均来自《数据库系统概念》&#xff08;黑宝书&#xff09;、山东大学李晖老师PPT。不可用于商业用途转发。 回顾 上周最后一个知识点说到数据库三级模式结构&#xff0c;在这个结构里面我们设立了模式/内模式映像、内模式/外模式映像&#xff0c;主…

Python之闭包

一、概念 在函数嵌套的前提下&#xff0c;内层函数引用外层函数的变量(包括参数)&#xff0c;外层函数又把内层函数当做返回值进行返回。 这个内层函数所引用的外层变量称为 “闭包” def test(): # 外层函数a 33 # 外部变量def test2(): # 内层函数print(a)return test2newFu…

网络计算机

TCP/IP四层模型 应用层&#xff1a;位于传输层之上&#xff0c;主要提供两个设备上的应用程序之间信息交换的服务&#xff0c;它定义了信息交换的格式&#xff0c;消息会交给下一层传输层来传递。我们把应用层交互的数据单元称为报文。应用层工作在操作系统的用户态&#xff0…

Android自定义view从入门到高级

简介 什么是自定义view&#xff1f;我认为只要不是编译器直接提供可以使用的view&#xff0c;都可以认为是自定义view。自定义view主要分为两大类&#xff0c;第一类自定义view可以通过系统提供的各种view组合&#xff0c;样式变化实现的view。第二类是通过继承view或者ViewGro…

捍卫数据保护:预防和缓解.mallox勒索病毒的威胁

导言&#xff1a; 在当今数字化时代&#xff0c;我们与世界各地的人们通过网络连接在一起&#xff0c;享受着前所未有的便利。然而&#xff0c;随着科技的进步&#xff0c;网络犯罪也在不断演变&#xff0c;.mallox勒索病毒便是其中之一&#xff0c;给无数用户带来了困扰。本文…

【SpringCloud微服务实战07】Sentinel 服务保护

Sentinel 是阿里巴巴开源的一款微服务流量控制组件。主要作用: 流量控制:避免因瞬间高并发流量而导致服务故障流。超时处理、线程隔离、降级熔断:避免因服务故障引起的雪崩问题。一、Sentinel 安装 1、安装Sentinel控制台,下载jar包并启动:Releases alibaba/Sentinel G…

【HiVT】HiVT轨迹预测代码环境配置及训练

0.简介 github项目链接 论文链接 Argoverse 1.1验证集的预期性能是&#xff1a; Models minADE minFDE MR HiVT-64 0.69 1.03 0.10 HiVT-128 0.66 0.97 0.09 1. 拉取代码仓库 git clone https://github.com/ZikangZhou/HiVT.git cd HiVT2. 创建conda环境 conda create -n H…

Java 启动参数 -- 和 -D写法的区别

当我们配置启动1个java 项目通常需要带一些参数 例如 -Denv uat , --spring.profiles.activedev 这些 那么用-D 和 – 的写法区别是什么&#xff1f; 双横线写法 其中这种写法基本上是spring 和 spring 框架独有 最常用的无非是就是上面提到的 --spring.profiles.activede…

LiveGBS流媒体平台GB/T28181功能-海康摄像头国标语音对讲大华摄像头国标语音对讲GB28181语音对讲需要的设备及服务准备

LiveGBS海康摄像头国标语音对讲大华摄像头国标语音对讲GB28181语音对讲需要的设备及服务准备 1、背景2、准备2.1、服务端必备条件&#xff08;注意&#xff09;2.2、准备语音对讲设备2.2.1、 大华摄像机2.2.1.1、 配置接入示例2.2.1.2、 配置音频通道编号 2.2.2、 海康摄像机2.…

基于YOLOv8/YOLOv7/YOLOv6/YOLOv5的危险物品检测系统(深度学习模型+PySide6界面+训练数据集+Python代码)

摘要&#xff1a;本文深入介绍了一个采用深度学习技术的危险物品识别系统&#xff0c;该系统融合了最新的YOLOv8算法&#xff0c;并对比了YOLOv7、YOLOv6、YOLOv5等早期版本的性能。该系统在处理图像、视频、实时视频流及批量文件时&#xff0c;能够准确识别和分类各种危险物品…

jenkins部署go应用 基于docker

丢弃旧的的构建 github 拉取代码 拉取代码排除指定配置文件 报错 环境变量失效 服务器版本为1.21.6 但是一直没有生效

【大模型系列】根据文本检索目标(DINO/DINOv2/GroundingDINO)

文章目录 1 DINO(ICCV2021, Meta)1.1 数据增强1.2 损失函数 2 DINOv2(CVPR2023, Meta)2.1 数据采集方式2.2 训练方法 3 Grounding DINO3.1 Grounding DINO设计思路3.2 网络结构3.2.1 Feature Extraction and Enhancer3.2.2 Language-Guided Query Selection3.2.3 Cross-Modalit…