XLSX + LuckySheet + LuckyExcel + Web Worker实现前端的excel预览

文章目录

    • 功能简介
    • 简单代码实现
    • web worker 版本
    • 效果
    • 参考

功能简介

  1. 通过LuckyExcel的transformExcelToLucky方法, 我们可以把一个文件直接转成LuckySheet需要的json字符串, 之后我们就可以用LuckySheet预览excel
  2. LuckyExcel只能解析xlsx格式的excel文件,因此对于xls和csv的格式,我们需要通过XLSX来转化成xlsx格式,但在转化过程中会丢失样式
  3. 对于excel中存在很多的空白行,在显示的时候可能会出现卡顿,所以我们需要将过多的空白行移除

简单代码实现

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Excel File Upload and Preview with Luckysheet</title>
</head>
<body>

<!-- 文件上传控件 -->
<input type="file" id="fileUpload"/>

<!-- Luckysheet 的容器 -->
<div id="luckysheet" style="position: relative; width: 100%; height: 500px;"></div>
<script src="https://cdn.jsdelivr.net/npm/xlsx/dist/xlsx.full.min.js"></script>

<link rel='stylesheet' href='https://cdn.jsdelivr.net/npm/luckysheet@latest/dist/plugins/css/pluginsCss.css'/>
<link rel='stylesheet' href='https://cdn.jsdelivr.net/npm/luckysheet@latest/dist/plugins/plugins.css'/>
<link rel='stylesheet' href='https://cdn.jsdelivr.net/npm/luckysheet@latest/dist/css/luckysheet.css'/>
<link rel='stylesheet' href='https://cdn.jsdelivr.net/npm/luckysheet@latest/dist/assets/iconfont/iconfont.css'/>
<script src="https://cdn.jsdelivr.net/npm/luckysheet@latest/dist/plugins/js/plugin.js"></script>
<script src="https://cdn.jsdelivr.net/npm/luckysheet@latest/dist/luckysheet.umd.js"></script>


<script src="https://cdn.jsdelivr.net/npm/luckyexcel/dist/luckyexcel.umd.js"></script>

<script>
 
 const _xlsxType = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet';
  const  _xlsType = 'application/vnd.ms-excel';
  const  _csvType = 'text/csv';

  //如果后端是以流的方式返回,可以调用这个方法
  const handleExcel = (res, fileName) => {
    const file = getExcelFile(res, fileName);
    handleExcelFile(file);
  }


 // 获取Excel文件
  const getExcelFile = (res, fileName) => {
  // 根据文件后缀名判断文件类型
    if (fileName.endsWith('.xlsx')) {
      return new File([res], fileName, {type: _xlsxType});
    } else if (fileName.endsWith('.xls')) {
      return new File([res], fileName, {type: _xlsType});
    } else if (fileName.endsWith('.csv')) {
      return new File([res], fileName, {type: _csvType});
    } else {
      throw new Error("Unsupported file type");
    }
  }
  
	// 处理Excel文件
  const handleExcelFile = (file) => {
    const fileName = file.name;
    // 根据文件后缀名判断文件类型并进行处理
    if (fileName.endsWith('.xlsx')) {
      console.log("handle excel for xlsx type..", fileName);
      handleExcelForXlsxType(file, fileName);
    } else if (fileName.endsWith('.xls') || fileName.endsWith('.csv')) {
      console.log("handle excel for xls or csv type..", fileName);
      handleExcelForXlsAndCsvType(file, fileName);
    } else {
      throw new Error("Unsupported file type");
    }
  }

// 处理xlsx类型的Excel文件
  const handleExcelForXlsxType = (file, fileName) => {
    const reader = new FileReader();
    reader.onload = function (event) {
      const data = new Uint8Array(event.target.result);
      const workbook = XLSX.read(data, {type: 'array'});
       // 获取Excel文件中的最大行数
      let maxRowCountFromExcel = getMaxRowCountFromExcel(workbook);
      // 如果行数大于100000,则处理Excel文件中的空行
      if (maxRowCountFromExcel > 1000000) {
        console.log("excel file has too many blank row..", maxRowCountFromExcel);
        handleBlankRowForExcelWithTooManyBlankRow(workbook);
        const xlsxFile = toXlsxExcelFile(workbook, fileName);
        createLuckySheet(xlsxFile);
      } else {
        createLuckySheet(file);
      }
    };
    reader.readAsArrayBuffer(file);
  }

// 处理xls和csv类型的Excel文件
  const handleExcelForXlsAndCsvType = (file, fileName) => {
    const reader = new FileReader();
     // 读取文件完成后的回调函数
    reader.onload = function (event) {
      const data = new Uint8Array(event.target.result);
        // 读取Excel文件内容
      const workbook = XLSX.read(data, {type: 'array'});
       // 将Excel文件转换为xlsx类型
      const xlsxFile = toXlsxExcelFile(workbook, fileName);
       // 处理xlsx类型的Excel文件
      handleExcelForXlsxType(xlsxFile, fileName);
    };
    // 以ArrayBuffer的形式读取文件
    reader.readAsArrayBuffer(file);
  }

/ 创建Luckysheet
  const createLuckySheet = (file) => {
  // 销毁已存在的Luckysheet
    window.luckysheet.destroy();
     // 将Excel文件转换为Luckysheet的json
    LuckyExcel.transformExcelToLucky(file, function (exportJson, luckysheetfile) {
      if (exportJson.sheets == null || exportJson.sheets.length === 0) {
        throw new Error("Failed to load excel file");
      }
      // 创建Luckysheet的配置项
      const options = {
        container: 'luckysheet',
        data: exportJson.sheets, // title: exportJson.info.name,
        // userInfo: exportJson.info.name.creator,
        column: 10,
        row: 10,
        showinfobar: false,
        sheetFormulaBar: true,
        showConfigWindowResize: false
      };
      // 创建Luckysheet
      window.luckysheet.create(options);
    });
  }
  // 获取Excel文件中的最大行数
  const getMaxRowCountFromExcel = (workbook) => {
    let maxRowCount = 0;
    if (workbook.SheetNames == null || workbook.SheetNames.length === 0) {
      return maxRowCount;
    }
    // 遍历每个sheet,获取最大行数
    workbook.SheetNames.forEach(sheetName => {
      const worksheet = workbook.Sheets[sheetName];
      if (worksheet['!ref'] === undefined) {
        return;
      }
      const range = XLSX.utils.decode_range(worksheet['!ref']);
      maxRowCount = maxRowCount + range.e.r;
    });
	console.log("max:", maxRowCount)
    return maxRowCount;
  }
  const reduceBlankRow = (row, range, worksheet) => {
   // 从给定的行开始,向上遍历到工作表的起始行
    while (row > range.s.r) {
     // 假设当前行是空的
      let allEmpty = true;
       // 遍历当前行的所有列
      for (let col = range.s.c; col <= range.e.c; col++) {
      // 获取当前单元格的引用
        const cell_ref = XLSX.utils.encode_cell({c: col, r: row});
         // 如果当前单元格不为空,则将allEmpty设置为false并跳出循环
        if (worksheet[cell_ref]) {
          allEmpty = false;
          break;
        }
      }
      // 如果当前行是空的,则将行数减一,否则跳出循环
      if (allEmpty) {
        row--;
      } else {
        break;
      }
    }
     // 更新工作表范围的结束行
    range.e.r = row;
     // 更新工作表的范围引用
    worksheet['!ref'] = XLSX.utils.encode_range(range.s, range.e);
  }
  // 处理Excel文件中的空行
  const handleBlankRowForExcelWithTooManyBlankRow = (workbook) => {
    if (workbook.SheetNames == null || workbook.SheetNames.length === 0) {
      return;
    }
     // 遍历每个sheet,处理空行
    workbook.SheetNames.forEach(sheetName => {
      const worksheet = workbook.Sheets[sheetName];
      if (worksheet['!ref'] === undefined) {
        return;
      }
      const range = XLSX.utils.decode_range(worksheet['!ref']);
      let row = range.e.r;
      reduceBlankRow(row, range, worksheet);
    });
  }
	// 将Excel文件转换为xlsx类型
  const toXlsxExcelFile = (workbook, fileName) => {
    const newWorkbook = XLSX.write(workbook, {bookType: 'xlsx', type: 'binary'});
    const data = new Uint8Array(newWorkbook.length);
    for (let i = 0; i < newWorkbook.length; i++) {
      data[i] = newWorkbook.charCodeAt(i);
    }
    return new File([data], fileName, {type: _xlsxType});
  }


 // 文件上传控件的change事件处理函数
  document.getElementById('fileUpload').addEventListener('change', function (e) {
 	 // 获取上传的文件
    const file = e.target.files[0];
     // 处理Excel文件
    handleExcelFile(file);

  });




</script>

</body>
</html>

web worker 版本

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Excel File Upload and Preview with Luckysheet</title>
</head>
<body>

<!-- 文件上传控件 -->
<input type="file" id="fileUpload"/>

<!-- Luckysheet 的容器 -->
<div id="luckysheet" style="position: relative; width: 100%; height: 500px;"></div>
<div id="worker" style="display:none">


  importScripts("https://cdn.jsdelivr.net/npm/xlsx/dist/xlsx.full.min.js")
  const _xlsxType = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet';
  const _xlsType = 'application/vnd.ms-excel';
  const _csvType = 'text/csv';
  const _maxRowCount = 5000000;


  self.addEventListener('message', (e) => {
  console.log('Worker get message:', e.data)
  handleExcel(e.data.data, e.data.fileName)
  });


  const handleExcel = (res, fileName) => {
  const file = getExcelFile(res, fileName);
  handleExcelFile(file);
  }

  const getExcelFile = (res, fileName) => {
  if (fileName.endsWith('.xlsx')) {
  return new File([res], fileName, {type: _xlsxType});
  } else if (fileName.endsWith('.xls')) {
  return new File([res], fileName, {type: _xlsType});
  } else if (fileName.endsWith('.csv')) {
  return new File([res], fileName, {type: _csvType});
  } else {
  throw new Error("Unsupported file type");
  }
  }

  const handleExcelFile = (file) => {
  const fileName = file.name;
  if (fileName.endsWith('.xlsx')) {
  console.log("handle excel for xlsx type..", fileName);
  handleExcelForXlsxType(file, fileName);
  } else if (fileName.endsWith('.xls') || fileName.endsWith('.csv')) {
  console.log("handle excel for xls or csv type..", fileName);
  handleExcelForXlsAndCsvType(file, fileName);
  } else {
  throw new Error("Unsupported file type");
  }
  }

  const handleExcelForXlsxType = (file, fileName) => {
  const reader = new FileReader();
  reader.onload = function (event) {
  const data = new Uint8Array(event.target.result);
  const workbook = XLSX.read(data, {type: 'array', cellDates: true});
  let maxRowCountFromExcel = getMaxRowCountFromExcel(workbook);
  if (maxRowCountFromExcel > _maxRowCount) {
  console.log("excel file has too many blank row..", maxRowCountFromExcel);
  handleBlankRowForExcelWithTooManyBlankRow(workbook);
  const xlsxFile = toXlsxExcelFile(workbook, fileName);
  createLuckySheet(xlsxFile);
  } else {
  createLuckySheet(file);
  }
  };
  reader.readAsArrayBuffer(file);
  }

  const handleExcelForXlsAndCsvType = (file, fileName) => {
  const reader = new FileReader();
  reader.onload = function (event) {
  const data = new Uint8Array(event.target.result);
  const workbook = XLSX.read(data, {type: 'array', cellDates: true});
  let maxRowCountFromExcel = getMaxRowCountFromExcel(workbook);
  if (maxRowCountFromExcel > _maxRowCount) {
  console.log("excel file has too many blank row..", maxRowCountFromExcel);
  handleBlankRowForExcelWithTooManyBlankRow(workbook);
  }
  const xlsxFile = toXlsxExcelFile(workbook, fileName);
  handleExcelForXlsxType(xlsxFile, fileName);
  };
  reader.readAsArrayBuffer(file);
  }

  const createLuckySheet = (file) => {
  const reader = new FileReader();
  reader.onload = (event => {
  postMessage({
  fileArrayBuffer: event.target.result ,
  fileName: file.name,
  })
  });
  reader.readAsArrayBuffer(file);

  }
  const getMaxRowCountFromExcel = (workbook) => {
  let maxRowCount = 0;
  if (workbook.SheetNames == null || workbook.SheetNames.length === 0) {
  return maxRowCount;
  }
  workbook.SheetNames.forEach(sheetName => {
  const worksheet = workbook.Sheets[sheetName];
  if (worksheet['!ref'] === undefined) {
  return;
  }
  const range = XLSX.utils.decode_range(worksheet['!ref']);
  maxRowCount = maxRowCount + range.e.r;
  });
  return maxRowCount;
  }
  const reduceBlankRow = (row, range, worksheet) => {
  while (row > range.s.r) {
  let allEmpty = true;
  for (let col = range.s.c; col <= range.e.c; col++) {
  const cell_ref = XLSX.utils.encode_cell({c: col, r: row});
  if (worksheet[cell_ref]) {
  allEmpty = false;
  break;
  }
  }
  if (allEmpty) {
  row--;
  } else {
  break;
  }
  }
  range.e.r = row;
  worksheet['!ref'] = XLSX.utils.encode_range(range.s, range.e);
  }
  const handleBlankRowForExcelWithTooManyBlankRow = (workbook) => {
  if (workbook.SheetNames == null || workbook.SheetNames.length === 0) {
  return;
  }
  workbook.SheetNames.forEach(sheetName => {
  const worksheet = workbook.Sheets[sheetName];
  if (worksheet['!ref'] === undefined) {
  return;
  }
  const range = XLSX.utils.decode_range(worksheet['!ref']);
  let row = range.e.r;
  reduceBlankRow(row, range, worksheet);
  });
  }

  const toXlsxExcelFile = (workbook, fileName) => {
  const newWorkbook = XLSX.write(workbook, {bookType: 'xlsx', type: 'binary'});
  const data = new Uint8Array(newWorkbook.length);
  for (let i = 0; i < newWorkbook.length; i++) {
  data[i] = newWorkbook.charCodeAt(i);
  }
  return new File([data], fileName, {type: _xlsxType});
  }


  self.addEventListener('error', function (event) {
  console.log("test....................", event)
  });


</div>
<script src="https://cdn.jsdelivr.net/npm/xlsx/dist/xlsx.full.min.js"></script>

<link rel='stylesheet' href='https://cdn.jsdelivr.net/npm/luckysheet@latest/dist/plugins/css/pluginsCss.css'/>
<link rel='stylesheet' href='https://cdn.jsdelivr.net/npm/luckysheet@latest/dist/plugins/plugins.css'/>
<link rel='stylesheet' href='https://cdn.jsdelivr.net/npm/luckysheet@latest/dist/css/luckysheet.css'/>
<link rel='stylesheet' href='https://cdn.jsdelivr.net/npm/luckysheet@latest/dist/assets/iconfont/iconfont.css'/>
<script src="https://cdn.jsdelivr.net/npm/luckysheet@latest/dist/plugins/js/plugin.js"></script>
<script src="https://cdn.jsdelivr.net/npm/luckysheet@latest/dist/luckysheet.umd.js"></script>


<script src="https://cdn.jsdelivr.net/npm/luckyexcel/dist/luckyexcel.umd.js"></script>

<script>


  const createLuckySheet = (exportJson) => {
    console.log(exportJson)
    window.luckysheet.destroy();
    const options = {
      container: 'luckysheet',
      data: exportJson.sheets, // title: exportJson.info.name,
      // userInfo: exportJson.info.name.creator,
      column: 10,
      row: 10,
      showinfobar: false,
      sheetFormulaBar: true,
      showConfigWindowResize: false
    };
    window.luckysheet.create(options);

  }

  const createLuckySheetByFileArrayBuffer = (arrayBuffer, fileName) => {
    const xlsxTtpe = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet';
    const file = new File([arrayBuffer], fileName, {type: xlsxTtpe});
    LuckyExcel.transformExcelToLucky(file, function (exportJson, luckysheetfile) {
      createLuckySheet(exportJson);
    });
  }

  var blob = new Blob([document.querySelector('#worker').textContent]);
  var url = window.URL.createObjectURL(blob);
  var worker = new Worker(url);
  worker.addEventListener('message', (event) => {
    const data = event.data
    createLuckySheetByFileArrayBuffer(data.fileArrayBuffer, data.fileName)

  })

  document.getElementById('fileUpload').addEventListener('change', function (e) {
    const file = e.target.files[0];

    const reader = new FileReader();
    reader.onload = (event => {
      worker.postMessage({
        data: event.target.result,
        fileName: file.name
      })
    });
    reader.readAsArrayBuffer(file);

  });


</script>

</body>
</html>

效果

在这里插入图片描述

参考

https://juejin.cn/post/7211805251216031801
https://segmentfault.com/a/1190000043720845
https://juejin.cn/post/7232524757525659708
https://blog.csdn.net/q2qwert/article/details/130908294
https://www.cnblogs.com/ajaemp/p/12880847.html
https://blog.csdn.net/weixin_40775791/article/details/135409716
https://blog.csdn.net/u013113491/article/details/129106671

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

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

相关文章

机器学习——随机森林

随机森林 1、集成学习方法 通过构造多个模型组合来解决单一的问题。它的原理是生成多个分类器/模型&#xff0c;各自独立的学习和做出预测。这些预测最后会结合成组合预测&#xff0c;因此优于任何一个单分类得到的预测。 2、什么是随机森林&#xff1f; 随机森林是一个包含…

Midjourney 预设

使用命令/settings 进入预设,根据点击不同选项来配置。 🌹 1. 设置工作所使用的模型版本。 1️⃣ MJ Version 1 2️⃣ MJ Version 2 3️⃣ MJ Version 3 4️⃣ MJ Version 4 5️⃣ MJ Version 5 5️⃣ MJ Version 5.1 🔧Raw Mode 🌈 Niji Version 4 🍎 Niji Versio…

【pytorch16】MLP反向传播

链式法则回顾 多输出感知机的推导公式回顾 只与w相关的输出节点和输入节点有关 多层多输入感知机 扩展为多层感知机的话&#xff0c;意味着还有一些层&#xff08;理解为隐藏层σ函数&#xff09;&#xff0c;暂且设置为 x j x_{j} xj​层 对于 x j x_{j} xj​层如果把前面的…

Vue联调Java后台操作性强教程

本人详解 作者:王文峰,参加过 CSDN 2020年度博客之星,《Java王大师王天师》 公众号:JAVA开发王大师,专注于天道酬勤的 Java 开发问题中国国学、传统文化和代码爱好者的程序人生,期待你的关注和支持!本人外号:神秘小峯 山峯 转载说明:务必注明来源(注明:作者:王文峰…

C++入门 容器适配器 / stack queue模拟实现

目录 容器适配器 deque的原理介绍 stack模拟实现 queue模拟实现 priority_queue模拟实现 仿函数 容器适配器 适配器是一种设计模式(设计模式是一套被反复使用的、多数人知晓的、经过分类编目的、代码设计经验的总 结)&#xff0c;该种模式是将一个类的接口转换成客户希望…

关于GIS的概念方面在前端编程中的理解

关于GIS的概念方面在前端编程中的理解 一. 什么是gis二. 关于地球的建模(了解)三. GIS坐标系表现形式四.GIS的数据4.1 矢量数据4.2 栅格数据4.3 矢量数据和栅格数据的不同 一. 什么是gis 地理坐标系统&#xff0c;其目的就是通过地理坐标系可以确定地球上任何一点的位置。 二. …

介绍 pg_later:受 Snowflake 启发的 Postgres 异步查询#postgresql认证

#PG培训#PG考试#postgresql培训#postgresql考试 为什么要使用异步查询&#xff1f; 想象一下&#xff0c;您启动了一项长期维护工作。您在执行过程中离开&#xff0c;但回来后发现&#xff0c;由于笔记本电脑关机&#xff0c;该工作在几个小时前就被中断了。您不希望这种情况…

web基础与HTTP协议(企业网站架构部署与优化)

补充&#xff1a;http服务首页文件在/var/www/html下的&#xff0c;一定是index.html命名的文件。才会显示出来。 如果该路径下没有相应的文件&#xff0c;会显示/usr/share/httpd/noindex下的index.html文件。 如果/usr/share/httpd/noindex没有index.html文件&#xff0c;会…

Spring MVC 获取请求数据的四种方式,以及获取请求头数据,获取Cookie 的数据,设置Spring MVC 的字符集编码过滤器

1. Spring MVC 获取请求数据的四种方式&#xff0c;以及获取请求头数据&#xff0c;获取Cookie 的数据&#xff0c;设置Spring MVC 的字符集编码过滤器 文章目录 1. Spring MVC 获取请求数据的四种方式&#xff0c;以及获取请求头数据&#xff0c;获取Cookie 的数据&#xff0c…

昇思MindSpore学习笔记4-01生成式--CycleGAN图像风格迁移互换

摘要&#xff1a; 记录了昇思MindSpore AI框架用循环对抗生成网络模型CycleGAN实现图像匹配的方法、步骤。包括环境准备、数据集下载、数据加载和预处理、构建生成器和判别器、优化、模型训练和推理等。 1.模型介绍 1.1模型简介 CycleGAN(Cycle Generative Adversarial Netwo…

黑科技带来时尚的体验,Umelody悠律凝声环开放式耳机评测

如今的蓝牙耳机&#xff0c;已经有了很多种不同的风格&#xff0c;但是却很少有什么创新的。直至近期&#xff0c;耳挂式蓝牙耳机成为了开放式耳机的热点&#xff0c;其设计和风格都非常与众不同&#xff0c;那它体验如何&#xff0c;有什么优势呢&#xff1f; 本次体验&#…

����: �Ҳ������޷��������� javafx.fxml ԭ��: java.lang.ClassNotFoundException解决方法

如果你出现了这个问题&#xff0c;恭喜你&#xff0c;你应该会花很多时间去找解决方法。别问我怎么知道的... 解决方法&#xff1a; 出现乱码的原因&#xff1a;配置vm时 这些配置看似由有空格&#xff0c;换行&#xff0c;实则没有。所以解决办法就是&#xff0c;重新配置你…

中英双语介绍日本东京(Tokyo)

中文版 东京介绍 东京是日本的首都&#xff0c;也是日本的政治、经济、文化和国际交流中心。以下是对东京的详细介绍&#xff0c;包括其地理位置、人口、经济、教育、文化和主要景点。 地理位置 东京位于日本关东地区的南部&#xff0c;地理坐标大致为北纬35度41分&#xf…

多链路聚合通信路由在应急救援活动中的重要性及解决方案

在应急救援指挥活动中&#xff0c;多链路聚合通信设备如同一座坚固的桥梁&#xff0c;将信息快速、准确地传递至每一个角落。面对复杂多变的救援现场&#xff0c;这类设备展现了其卓越的适应性和稳定性。 想象一下&#xff0c;当灾害突然降临&#xff0c;信息的传递变得至关重…

yolov5 json 和 txt数据格式关系

训练阶段 和 推理阶段数据格式转换说明 关于yolov5 数据格式一直以来都傻傻分不清楚&#xff0c;这下进行了一个梳理&#xff0c;做了笔记&#xff0c;也希望可帮助到有需要的有缘人~ 转换部分代码

Transform Data with SQL

rm -r dp-203 -f git clone https://github.com/MicrosoftLearning/dp-203-azure-data-engineer dp-203 cd dp-203/Allfiles/labs/01 ./setup.ps1 -- This is auto-generated code SELECTTOP 100 * FROMOPENROWSET(BULK https://datalakexxxxxxx.dfs.core.windows.net/fil…

在Apache HTTP服务器上配置 TLS加密

安装mod_ssl软件包 [rootlocalhost conf.d]# dnf install mod_ssl -y此时查看监听端口多了一个443端口 自己构造证书 [rootlocalhost conf.d]# cd /etc/pki/tls/certs/ [rootlocalhost certs]# openssl genrsa > jiami.key [rootlocalhost certs]# openssl req -utf8 -n…

docker buildx 交叉编译设置

dockerd配置文件 /etc/docker/daemon.json设置&#xff1a; rootubuntu:/etc/docker# cat daemon.json {"insecure-registries":["localhost:5000","127.0.0.1:5000","172.16.67.111:5000"],"features": {"buildkit&…

磁力泵与屏蔽泵

1.磁力泵的工作原理 磁力传动是利用磁体能吸引铁磁物质以及磁体或磁场之间有磁力作用的特性&#xff0c;而非铁磁物质不影响或很少影响磁力的大小&#xff0c;因此可以无接触地透过非磁导体&#xff08;隔离套&#xff09;进行动力传输。磁力传动可分为同步或异步设计。 大多数…

基于深度学习的人脸多任务识别(附代码)

项目说明 本项目为人脸多任务识别(单输入&#xff0c;多输出)&#xff0c;可以同时输出人脸关键点、性别和年龄。 采用了两个算法进行应用的实现&#xff0c;人脸目标检测和人脸多任务识别。 其中人脸目标检测采用YOLOV5进行实现&#xff0c;主要对人脸部分进行截取&#xf…