NPOI实战:Excel表格复制Sheet与插入图片的完整指南(附代码)
NPOI深度实战解锁Excel自动化处理的高级技巧与避坑指南如果你正在用C#处理Excel并且厌倦了那些庞大、笨重的商业组件NPOI很可能已经进入了你的视野。这个开源、免费的.NET库让开发者能够在不依赖Office软件的情况下直接读写Excel、Word等文档。但说实话官方文档有时过于简略社区里的代码片段也常常是“知其然不知其所以然”。今天我们不谈那些基础的单元格读写而是聚焦于两个在实际项目中高频出现、却又容易踩坑的“硬骨头”如何优雅地复制Sheet尤其是跨工作簿以及如何精准地在Excel中插入并控制图片。我会结合真实的项目经验分享经过验证的完整代码并剖析那些官方文档里没写的细节和陷阱。1. 理解NPOI的核心对象模型一切操作的基础在开始“复制”和“插入”这些具体动作之前我们必须先建立起对NPOI对象模型的清晰认知。这就像盖房子前要看懂建筑图纸能让你在编码时游刃有余而不是盲目地复制粘贴代码。NPOI主要处理两种Excel文件格式.xlsHSSF和.xlsxXSSF。对于现代开发.xlsx是绝对的主流因此我们主要使用XSSFWorkbook类。一个Workbook代表一个Excel文件里面包含多个Sheet工作表。每个Sheet由Row行和Cell单元格构成网格。理解这个层级关系至关重要。注意HSSFWorkbook用于.xlsXSSFWorkbook用于.xlsx。两者接口IWorkbook,ISheet等基本一致但内部实现不同。混用可能导致异常。当你打开一个现有文件时典型的初始化代码如下using NPOI.XSSF.UserModel; // 针对.xlsx using NPOI.HSSF.UserModel; // 针对.xls using System.IO; // 打开一个现有的.xlsx文件 string filePath C:\Reports\Template.xlsx; FileStream fs new FileStream(filePath, FileMode.Open, FileAccess.ReadWrite); XSSFWorkbook workbook new XSSFWorkbook(fs);这里有一个常见的性能与资源管理陷阱FileStream和Workbook对象都需要妥善关闭。更优雅的做法是使用using语句块using (FileStream fs new FileStream(filePath, FileMode.Open, FileAccess.Read)) { XSSFWorkbook workbook new XSSFWorkbook(fs); // ... 你的操作逻辑 // 保存更改 using (FileStream outFs new FileStream(outputPath, FileMode.Create)) { workbook.Write(outFs); } // workbook 会在using块结束时通过其内部机制释放资源但注意它本身不继承IDisposable。 // 对于复杂操作确保所有流被正确关闭是关键。 }2. Sheet的复制艺术从简单克隆到深度拷贝复制一个Sheet听起来简单但根据你的需求不同实现方式天差地别。NPOI本身提供了基础的CopySheet方法但它有局限性。2.1 同一工作簿内的快速克隆如果你的需求只是在同一个Excel文件内创建一个Sheet的副本NPOI的内置方法是最快捷的。ISheet sourceSheet workbook.GetSheet(原始数据); // 方法1使用CopySheet方法并指定新Sheet的名称 ISheet clonedSheet workbook.CloneSheet(workbook.GetSheetIndex(sourceSheet), 数据备份); // 或者如果你已经有了一个目标Sheet对象比如新创建的可以 // workbook.SetSheetName(workbook.GetSheetIndex(clonedSheet), 数据备份);这个CloneSheet方法会复制Sheet的内容和大部分格式但它有一个众所周知的缺陷它不复制合并的单元格区域。如果你的模板Sheet里有跨行跨列的合并单元格克隆后的Sheet里这些合并状态会丢失数据会散落在各个独立单元格中这通常不是我们想要的结果。2.2 跨工作簿的深度复制一个健壮的解决方案更多时候我们需要从一个模板文件Template.xlsx复制一个设计好的Sheet到新生成的文件中。这时我们需要手动实现一个“深度拷贝”方法确保样式、数据、公式、合并单元格等元素一个不落。下面这个SheetCloner类是我在多个项目中提炼出来的实用工具。它解决了内置方法的不足并提供了是否复制单元格值的选项。public static class SheetCloner { /// summary /// 深度复制单元格样式 /// /summary public static void CopyCellStyle(IWorkbook destWorkbook, ICellStyle sourceStyle, ICellStyle destStyle) { // 对齐方式 destStyle.Alignment sourceStyle.Alignment; destStyle.VerticalAlignment sourceStyle.VerticalAlignment; destStyle.WrapText sourceStyle.WrapText; destStyle.Indention sourceStyle.Indention; destStyle.Rotation sourceStyle.Rotation; // 边框样式与颜色 destStyle.BorderTop sourceStyle.BorderTop; destStyle.BorderRight sourceStyle.BorderRight; destStyle.BorderBottom sourceStyle.BorderBottom; destStyle.BorderLeft sourceStyle.BorderLeft; destStyle.TopBorderColor sourceStyle.TopBorderColor; destStyle.RightBorderColor sourceStyle.RightBorderColor; destStyle.BottomBorderColor sourceStyle.BottomBorderColor; destStyle.LeftBorderColor sourceStyle.LeftBorderColor; // 填充背景色 destStyle.FillPattern sourceStyle.FillPattern; destStyle.FillForegroundColor sourceStyle.FillForegroundColor; destStyle.FillBackgroundColor sourceStyle.FillBackgroundColor; // 数据格式如日期、货币 destStyle.DataFormat sourceStyle.DataFormat; // 字体这是关键且易错的一步 IFont sourceFont sourceStyle.GetFont(destWorkbook); IFont newFont destWorkbook.CreateFont(); newFont.FontHeightInPoints sourceFont.FontHeightInPoints; newFont.FontName sourceFont.FontName; newFont.IsBold sourceFont.IsBold; newFont.IsItalic sourceFont.IsItalic; newFont.Underline sourceFont.Underline; newFont.Color sourceFont.Color; destStyle.SetFont(newFont); } /// summary /// 复制整个Sheet /// /summary /// param namesourceSheet源Sheet/param /// param namedestSheet目标Sheet/param /// param namecopyValue是否复制单元格的值/param public static void CopySheetContent(ISheet sourceSheet, ISheet destSheet, bool copyValue true) { // 1. 首先处理合并单元格区域 CopyMergedRegions(sourceSheet, destSheet); // 2. 遍历每一行 for (int rowIndex 0; rowIndex sourceSheet.LastRowNum; rowIndex) { IRow sourceRow sourceSheet.GetRow(rowIndex); if (sourceRow null) continue; // 跳过空行 IRow destRow destSheet.CreateRow(rowIndex); destRow.Height sourceRow.Height; // 复制行高 // 3. 遍历行中的每一个单元格 for (int cellIndex 0; cellIndex sourceRow.LastCellNum; cellIndex) { ICell sourceCell sourceRow.GetCell(cellIndex); if (sourceCell null) continue; ICell destCell destRow.CreateCell(cellIndex); CopyCell(sourceSheet.Workbook, destSheet.Workbook, sourceCell, destCell, copyValue); } } // 4. 复制列宽这是一个经常被忽略但很重要的细节 for (int i 0; i sourceSheet.GetRow(0)?.LastCellNum; i) { destSheet.SetColumnWidth(i, sourceSheet.GetColumnWidth(i)); } } private static void CopyMergedRegions(ISheet source, ISheet dest) { for (int i 0; i source.NumMergedRegions; i) { var mergedRegion source.GetMergedRegion(i); dest.AddMergedRegion(mergedRegion); } } private static void CopyCell(IWorkbook sourceWb, IWorkbook destWb, ICell sourceCell, ICell destCell, bool copyValue) { // 复制样式 ICellStyle newStyle destWb.CreateCellStyle(); CopyCellStyle(destWb, sourceCell.CellStyle, newStyle); destCell.CellStyle newStyle; // 根据单元格类型复制值 if (copyValue) { switch (sourceCell.CellType) { case CellType.String: destCell.SetCellValue(sourceCell.StringCellValue); break; case CellType.Numeric: // 特别注意判断是否为日期格式 if (DateUtil.IsCellDateFormatted(sourceCell)) { destCell.SetCellValue(sourceCell.DateCellValue); // 确保目标单元格也应用日期格式 ICellStyle dateStyle destWb.CreateCellStyle(); CopyCellStyle(destWb, sourceCell.CellStyle, dateStyle); destCell.CellStyle dateStyle; } else { destCell.SetCellValue(sourceCell.NumericCellValue); } break; case CellType.Boolean: destCell.SetCellValue(sourceCell.BooleanCellValue); break; case CellType.Formula: // 复制公式时需注意公式中的引用可能因Sheet名改变而失效 destCell.SetCellFormula(sourceCell.CellFormula); break; case CellType.Error: destCell.SetCellErrorValue(sourceCell.ErrorCellValue); break; case CellType.Blank: default: // 空白单元格无需操作 break; } } } }使用示例从模板文件复制Sheet到新工作簿// 打开模板工作簿 XSSFWorkbook templateWorkbook; using (var fs new FileStream(ReportTemplate.xlsx, FileMode.Open)) { templateWorkbook new XSSFWorkbook(fs); } // 创建新的目标工作簿 XSSFWorkbook newWorkbook new XSSFWorkbook(); ISheet newSheet newWorkbook.CreateSheet(月度报告); // 创建空Sheet // 获取模板Sheet ISheet templateSheet templateWorkbook.GetSheet(Template); // 使用工具类深度复制 SheetCloner.CopySheetContent(templateSheet, newSheet, copyValue: true); // 保存新工作簿 using (var outFs new FileStream(MonthlyReport_202310.xlsx, FileMode.Create)) { newWorkbook.Write(outFs); }2.3 删除Sheet的注意事项删除Sheet相对简单但要注意索引的变动。// 方法1通过Sheet名称删除 int sheetIndex workbook.GetSheetIndex(待删除Sheet名); if (sheetIndex 0) { workbook.RemoveSheetAt(sheetIndex); } // 方法2直接通过索引删除谨慎使用 // workbook.RemoveSheetAt(2); // 删除索引为2的Sheet从0开始 // 重要删除操作是立即生效的并且会改变剩余Sheet的索引。 // 例如删除索引1的Sheet后原来索引为2的Sheet会变成索引1。 // 在循环中删除多个Sheet时建议从后往前删。 for (int i workbook.NumberOfSheets - 1; i 0; i--) { if (workbook.GetSheetAt(i).SheetName.Contains(Temp)) { workbook.RemoveSheetAt(i); } }3. 在Excel中精准插入与操控图片在报表中插入Logo、图表截图或产品图片是常见需求。NPOI插入图片的核心在于理解IClientAnchor对象它定义了图片的位置和大小。3.1 基础插入将图片放入单元格首先你需要将图片文件读入字节数组。byte[] imageBytes File.ReadAllBytes(C:\Logo\company_logo.png);然后将图片添加到工作簿并获取一个图片索引。// 假设我们有一个名为 sheet 的工作表对象 int pictureIndex workbook.AddPicture(imageBytes, PictureType.PNG); // PictureType 可以是 PNG, JPEG, EMF, WMF, DIB, PICT, TIFF 等接下来创建绘图容器和锚点这是定位的关键。IDrawing drawing sheet.CreateDrawingPatriarch(); // 每个Sheet需要一个绘图容器 IClientAnchor anchor workbook.GetCreationHelper().CreateClientAnchor();IClientAnchor的构造函数参数决定了图片的位置。最常用的构造函数是// CreateClientAnchor(dx1, dy1, dx2, dy2, col1, row1, col2, row2) // col1, row1: 图片左上角锚定的单元格列行从0开始计数。 // col2, row2: 图片右下角锚定的单元格。 // dx1, dy1: 在左上角单元格内的偏移量以英制单位1/1024 of a column width/row height。 // dx2, dy2: 在右下角单元格内的偏移量。一个典型的例子将图片插入到B2单元格即第1列第1行索引从0开始并让图片填充B2到D5这个矩形区域。anchor.Col1 1; // B列 (索引1) anchor.Row1 1; // 第2行 (索引1) anchor.Col2 4; // D列的下一个边界即到D列 (索引3) 的右侧所以用4 anchor.Row2 5; // 第5行的下一个边界即到第5行 (索引4) 的下方所以用5 anchor.Dx1 0; anchor.Dy1 0; anchor.Dx2 1023; // 在目标单元格内的最大横向偏移 anchor.Dy2 255; // 在目标单元格内的最大纵向偏移单位与行高相关通常用255 IPicture picture drawing.CreatePicture(anchor, pictureIndex); // picture.Resize(); // 谨慎使用Resize它可能破坏预设的锚点大小。通常让锚点决定大小即可。3.2 高级技巧控制图片大小与位置精确控制像素大小Excel中的位置单位不是像素这很让人头疼。一个近似的方法是先插入图片然后通过计算来调整。但更实用的方法是先在设计好的模板Excel里手动插入一张图片调整到满意的大小和位置然后用NPOI读取这个文件的锚点参数作为你代码的参考值。保持图片宽高比picture.Resize()方法可以等比例缩放图片以适配锚点区域但效果有时不理想。更好的做法是手动计算锚点的col2和row2使其形成的矩形区域符合你期望的宽高比。将图片设置为单元格背景NPOI没有直接设置单元格背景图片的API。变通方法是将图片锚定到该单元格并设置单元格的行高列宽与图片尺寸匹配同时将单元格内容文字置于图片上层通过Z-orderNPOI默认后创建的图形在上层。3.3 常见问题与排查图片不显示最常见的原因是图片字节数组为空或者PictureType枚举值与实际图片格式不匹配。确保文件路径正确并且使用正确的PictureType如PictureType.PNG对应.png文件。图片位置错乱仔细检查IClientAnchor的col1, row1, col2, row2参数。记住(col2, row2)定义的是右下角边界所在的单元格索引而不是偏移量。dx1, dy1, dx2, dy2才是单元格内的微调偏移。“对象不支持Resize属性或方法”错误这通常发生在使用HSSF.xls格式时某些旧版本或特定图片类型不支持Resize()。对于.xlsxXSSFResize()通常是可用的。如果遇到问题直接注释掉Resize()调用依靠锚点定义大小。内存消耗过大插入大量高分辨率图片会急剧增加工作簿的内存占用和文件大小。在服务器端生成报表时需要考虑对图片进行压缩或降低分辨率。4. 实战整合构建一个报表生成模块让我们把前面所有的知识点串联起来假设我们要完成一个任务基于一个带有标题、表格和Logo占位符的模板Sheet生成一份包含动态数据和自定义Logo的月度销售报告。步骤分解准备阶段设计好MonthlyReport_Template.xlsx文件。里面有一个名为Template的Sheet包含了所有固定格式表头、样式、合并单元格。在A1单元格预留了插入Logo的位置例如锚定在A1到B3区域。代码实现核心逻辑public class MonthlyReportGenerator { public void GenerateReport(string templatePath, string outputPath, ListSalesData data, byte[] companyLogo) { // 1. 加载模板 XSSFWorkbook workbook; using (FileStream fs new FileStream(templatePath, FileMode.Open, FileAccess.Read)) { workbook new XSSFWorkbook(fs); } // 2. 复制模板Sheet到新Sheet并重命名 ISheet templateSheet workbook.GetSheet(Template); ISheet reportSheet workbook.CloneSheet(workbook.GetSheetIndex(templateSheet)); workbook.SetSheetName(workbook.GetSheetIndex(reportSheet), DateTime.Now.ToString(yyyy-MM)); // 3. 可选如果需要深度复制确保合并单元格等则使用我们的SheetCloner // ISheet reportSheet workbook.CreateSheet(DateTime.Now.ToString(yyyy-MM)); // SheetCloner.CopySheetContent(templateSheet, reportSheet, true); // 4. 插入动态Logo if (companyLogo ! null companyLogo.Length 0) { int logoIndex workbook.AddPicture(companyLogo, PictureType.PNG); IDrawing drawing reportSheet.CreateDrawingPatriarch(); IClientAnchor anchor workbook.GetCreationHelper().CreateClientAnchor(); // 假设模板中Logo应该放在A1:B3区域 anchor.Col1 0; // A列 anchor.Row1 0; // 第1行 anchor.Col2 2; // 到B列右侧 (索引11) anchor.Row2 3; // 到第3行下方 (索引21) // 使用微小偏移让图片贴合单元格边缘 anchor.Dx1 0; anchor.Dy1 0; anchor.Dx2 1023; anchor.Dy2 255; drawing.CreatePicture(anchor, logoIndex); } // 5. 填充动态数据假设从第5行开始填充数据 int startRow 4; // 0-based index对应Excel第5行 foreach (var item in data) { IRow dataRow reportSheet.GetRow(startRow) ?? reportSheet.CreateRow(startRow); dataRow.CreateCell(0).SetCellValue(item.ProductName); dataRow.CreateCell(1).SetCellValue(item.SalesAmount); dataRow.CreateCell(2).SetCellValue(item.GrowthRate); // ... 设置单元格样式可以复用模板行的样式 startRow; } // 6. 删除原始的模板Sheet如果不需要保留 int templateIndex workbook.GetSheetIndex(Template); if (templateIndex 0) { workbook.RemoveSheetAt(templateIndex); } // 7. 保存文件 using (FileStream outFs new FileStream(outputPath, FileMode.Create)) { workbook.Write(outFs); } } } public class SalesData { public string ProductName { get; set; } public double SalesAmount { get; set; } public double GrowthRate { get; set; } }这个例子展示了如何将复制Sheet、插入图片、操作单元格数据以及删除Sheet等操作有机结合起来形成一个完整的自动化报表生成流程。在实际项目中你可能还需要处理更复杂的样式继承、公式更新、图表生成等问题但掌握了这些核心操作你已经具备了解决大部分NPOI高级应用场景的能力。记住多调试、多查阅NPOI源码和测试用例是深入掌握这个强大库的不二法门。

相关新闻

从ASK到QAM:深入解析线性调制技术如何塑造现代高速通信

从ASK到QAM:深入解析线性调制技术如何塑造现代高速通信

1. 从“开关灯”到“调色盘”:线性调制技术的演进之路 如果你用过对讲机,或者老式的收音机,你大概对“调频”(FM)和“调幅”(AM)这两个词不陌生。它们代表了模拟信号时代调制技术的两大流派。但…

2026/7/6 3:21:28 阅读更多 →
实测Qwen All-in-One:CPU环境秒级响应,打造轻量级AI助手

实测Qwen All-in-One:CPU环境秒级响应,打造轻量级AI助手

实测Qwen All-in-One:CPU环境秒级响应,打造轻量级AI助手 1. 引言:当AI助手遇上资源瓶颈 想象一下,你正在一台没有独立显卡的普通电脑上,想部署一个能理解你情绪、还能跟你聊天的智能助手。传统方案会告诉你&#xff…

2026/5/17 10:01:06 阅读更多 →
智能汽车HMI设计的未来:多模态交互与情感化体验

智能汽车HMI设计的未来:多模态交互与情感化体验

1. 从物理按键到“无感”交互:HMI的进化之路 十年前我刚入行做车载系统开发那会儿,车里最“智能”的交互可能就是那个能按下去“咔哒”响的空调旋钮。那时候的HMI,说白了就是一堆物理按键和几个单色小屏幕的组合,功能明确&#xf…

2026/7/4 20:48:53 阅读更多 →

最新新闻

YOLO26 改进 - C2PSA   C2PSA融合DML动态混合层(Dynamic Mixing Layer)轻量级设计优化局部细节捕获与通道适应性,提升超分辨率重建质量

YOLO26 改进 - C2PSA C2PSA融合DML动态混合层(Dynamic Mixing Layer)轻量级设计优化局部细节捕获与通道适应性,提升超分辨率重建质量

前言 本文介绍了动态混合层(DML),并将相关改进模块集成进YOLO26。DML是SRConvNet核心组件,用于解决轻量级图像超分辨率任务中特征捕捉和通道适应性问题。它通过通道扩展拆分、多尺度动态深度卷积、通道洗牌与融合等步骤&#xff…

2026/7/6 3:22:03 阅读更多 →
一碰自动计分,识别零误差!FSV9563 远距离 NFC 模组,台球馆智能化改造优选方案

一碰自动计分,识别零误差!FSV9563 远距离 NFC 模组,台球馆智能化改造优选方案

中文关键词:NFC 智能台球计分、FSV9563、NFC 自动识别台球、落球自动计分、远距离 NFC 感应 10CM、台球馆无人计分、台球桌智能化改造、商用台球自动统计、家用台球计分模组、NFC 台球标签、台球免人工计分、游乐设备智能检测英文关键词:NFC billiards a…

2026/7/6 3:22:03 阅读更多 →
Python爬虫经典案例第71篇:加密货币平台爬取:CoinGecko数据采集实战

Python爬虫经典案例第71篇:加密货币平台爬取:CoinGecko数据采集实战

1. 引言 加密货币市场近年来发展迅速,成为金融科技领域的热门话题。CoinGecko作为全球最大的加密货币数据平台之一,提供了超过13,000种加密货币的实时数据,包括价格、市值、交易量、链上数据等。对于加密货币投资者、量化交易员和区块链研究者而言,CoinGecko数据具有重要价…

2026/7/6 3:20:03 阅读更多 →
2026 最新 GPT 充值完整教程:从基础权益到 Pro 顶配升级,解锁全部 AI 高阶能力

2026 最新 GPT 充值完整教程:从基础权益到 Pro 顶配升级,解锁全部 AI 高阶能力

2026 最新 GPT 充值完整教程:从基础权益到 Pro 顶配升级,解锁全部 AI 高阶能力随着大模型技术持续迭代,GPT 全系功能不断更新,免费版本的算力配额、模型能力、使用场景限制越来越明显。无论是日常办公、文案创作、学术研究&#x…

2026/7/6 3:18:02 阅读更多 →
第五次作业提交

第五次作业提交

CSDN博客完整文章## 一、实验环境 远程连接工具:Xshell 操作系统:Ubuntu Linux 实验说明:所有命令均在Xshell终端实操,配套运行截图记录结果,梳理完整命令知识框架。 第一部分:Shell文本处理命令知识框架 1…

2026/7/6 3:18:02 阅读更多 →
密码学在区块链技术中的应用研究

密码学在区块链技术中的应用研究

开篇前言大家好,本次密码学与信息安全课程设计围绕密码学在区块链技术中的应用完成完整调研、方案设计与验证。很多人只知道区块链是分布式账本,却不知道整套区块链可信体系完全建立在各类密码学原语之上。 本文严格按照课程设计目录完整展开&#xff0c…

2026/7/6 3:18:02 阅读更多 →

日新闻

H2 与 MySQL 单元测试兼容性:5 个关键 SQL 语句差异与规避方案

H2 与 MySQL 单元测试兼容性:5 个关键 SQL 语句差异与规避方案

H2与MySQL单元测试兼容性:5个关键SQL语句差异与规避方案1. 单元测试中的数据库兼容性挑战在Java开发领域,单元测试是保证代码质量的重要环节。当应用涉及数据库操作时,测试环境的搭建往往成为开发者的痛点。H2数据库因其轻量级、内存模式和快…

2026/7/6 0:01:17 阅读更多 →
Windows任务栏终极清理指南:用RBTray一键隐藏窗口到系统托盘

Windows任务栏终极清理指南:用RBTray一键隐藏窗口到系统托盘

Windows任务栏终极清理指南:用RBTray一键隐藏窗口到系统托盘 【免费下载链接】rbtray A fork of RBTray from http://sourceforge.net/p/rbtray/code/. 项目地址: https://gitcode.com/gh_mirrors/rb/rbtray 你是否厌倦了Windows任务栏上密密麻麻的图标&…

2026/7/6 0:01:17 阅读更多 →
Visual C++ 运行时库一键安装终极指南:告别DLL缺失烦恼

Visual C++ 运行时库一键安装终极指南:告别DLL缺失烦恼

Visual C 运行时库一键安装终极指南:告别DLL缺失烦恼 【免费下载链接】vcredist AIO Repack for latest Microsoft Visual C Redistributable Runtimes 项目地址: https://gitcode.com/gh_mirrors/vc/vcredist 你是否曾经遇到过这样的情况:下载了…

2026/7/6 0:05:19 阅读更多 →

周新闻

B站视频下载神器BiliTools:5分钟学会轻松保存任何B站内容

B站视频下载神器BiliTools:5分钟学会轻松保存任何B站内容

B站视频下载神器BiliTools:5分钟学会轻松保存任何B站内容 【免费下载链接】BiliTools A cross-platform bilibili toolbox. 跨平台哔哩哔哩工具箱,支持下载视频、番剧等等各类资源 项目地址: https://gitcode.com/GitHub_Trending/bilit/BiliTools …

2026/7/5 0:03:34 阅读更多 →
威胁模型全解析:从新手入门到实战应用,助你构建安全产品!

威胁模型全解析:从新手入门到实战应用,助你构建安全产品!

威胁模型的陌生现状在忙碌疲惫的一天里,参与了关于混合后量子密码学的讨论,应付端点攻击找茬的人,还参与留言板讨论后,发现“威胁模型”对多数人仍是陌生概念,且多被当作时髦用语。有趣的相关画作有一幅由 Embyr 创作的…

2026/7/5 0:03:34 阅读更多 →
渗透测试入门指南:从零基础到实战环境搭建

渗透测试入门指南:从零基础到实战环境搭建

1. 从“看热闹”到“入门”:我理解的渗透测试到底是什么?每次看到新闻里说某个大公司的数据被“黑”了,或者某个网站被攻击导致服务瘫痪,你是不是和我一样,心里会冒出两个念头:一是“这黑客真厉害”&#x…

2026/7/5 0:07:38 阅读更多 →

月新闻