手把手教你用Blob实现前端文件预览与下载(2023最新版)
手把手教你用Blob实现前端文件预览与下载2023最新版最近在重构一个内部文档管理系统时我又一次遇到了那个经典的前端需求如何优雅地处理来自后端的文件流并实现预览和下载无论是用户上传的图片需要即时预览还是从服务器获取的PDF报告需要提供下载核心都绕不开浏览器中的Blob对象。我发现很多开发者对这个概念的理解还停留在“知道有这么个东西”的层面真正用起来时要么复制粘贴网上的代码要么对性能问题和内存泄漏视而不见。这篇文章我想结合自己最近踩过的几个坑和优化实践从头到尾、由浅入深地聊聊Blob目标是让你不仅能写出可用的代码更能写出高效、健壮、易于维护的代码。BlobBinary Large Object是浏览器提供的一个原生对象它代表了一段不可变的、原始数据的类文件对象。简单来说它就像是一个装着二进制数据的“盒子”你可以把图片、PDF、Excel甚至是一段文本的原始字节数据放进去。前端工程师之所以需要它是因为现代Web应用越来越复杂我们经常需要在不刷新页面的情况下动态地处理服务器返回的二进制数据文件流或者处理用户通过input typefile选择的本地文件。Blob配合URL.createObjectURL()和FileReader这两个API就构成了前端处理文件数据的核心工具箱。这篇文章适合所有需要在前端与文件打交道的开发者无论你是刚入门的新手还是想深化理解、优化现有代码的老手。1. 理解Blob不只是二进制数据的容器在深入代码之前我们有必要把Blob这个基础概念吃透。很多人把它简单理解为“一个文件”这其实不够准确。Blob对象本身并不关心它内部数据的“意义”它只负责存储原始的二进制数据并附带一些元信息比如数据的MIME类型type属性和大小size属性。1.1 Blob的创建与基本属性创建一个Blob对象非常直接。最常用的构造函数接受一个数组作为数据源这个数组可以包含ArrayBuffer、ArrayBufferView、Blob、String等以及一个可选的配置对象。// 从文本字符串创建Blob const textBlob new Blob([Hello, World!], { type: text/plain }); console.log(textBlob.size); // 13 (字符串的字节长度) console.log(textBlob.type); // text/plain // 从多个数据源组合创建Blob const part1 new Uint8Array([72, 101, 108, 108, 111]); // Hello的ASCII码 const part2 , ; const part3 new Blob([World!]); const combinedBlob new Blob([part1, part2, part3], { type: text/plain });这里有几个关键点需要注意数据不可变一旦Blob被创建其内容就无法更改。这保证了数据在传递过程中的一致性。MIME类型的重要性type属性至关重要它决定了浏览器如何解释这段二进制数据。一个image/png的Blob会被渲染成图片而application/pdf则可能触发PDF阅读器插件或浏览器的内置预览。如果类型错误或缺失预览和下载行为会变得不可预测。BlobvsFileFile对象继承自Blob可以看作是带有额外元信息如name、lastModified的特化Blob。用户通过文件输入框选择的文件就是File对象。1.2 Blob、ArrayBuffer与文件流的关系在实际项目中我们接触Blob的路径主要有两条从用户本地来通过input typefile获取的File对象。从服务器来通过fetch或XMLHttpRequest请求将响应类型设置为blob获得。这里容易混淆的是ArrayBuffer。ArrayBuffer是代表通用、固定长度的原始二进制数据缓冲区是更低层级的表示。而Blob是更高级的、类文件的封装。当从网络获取文件流时浏览器底层处理的是ArrayBuffer但通过response.blob()方法它被方便地包装成了Blob对象。提示Blob可以转换为ArrayBuffer通过FileReader反之ArrayBuffer也可以用来构造Blob。理解它们的区别有助于你在不同场景下选择最合适的处理方式。为了更清晰地对比这几个核心概念我整理了一个简单的表格特性BlobArrayBufferFile本质类文件对象不可变二进制数据块原始二进制数据缓冲区继承自Blob代表用户文件系统中的文件关键属性size,typebyteLengthname,lastModified,size,type创建方式new Blob(array, options)new ArrayBuffer(length)用户通过input选择或new File(parts, name, options)主要用途存储数据生成对象URL用于预览/下载底层二进制操作如解码音频、图像处理代表用户选择的文件用于上传或本地处理可读性需要通过FileReader或对象URL间接读取需要通过TypedArray或DataView视图来操作同Blob也可直接访问文件元信息理解这张表你就能明白为什么在大多数前端文件处理场景中Blob是我们的首选接口——它提供了最接近“文件”的抽象使用起来最方便。2. 核心实战从URL到Blob再到预览与下载理论讲得再多不如一行代码。让我们进入最核心的实战环节。我将以最常见的“从服务器获取文件并下载”为例拆解每一步并对比不同实现方案的优劣。2.1 方案一使用现代fetch API首选推荐这是目前最推荐、代码最简洁清晰的方式。fetchAPI天然支持blob响应类型并且基于Promise便于异步处理和错误捕获。/** * 使用fetch API下载文件 * param {string} fileUrl - 文件的服务器地址 * param {string} fileName - 用户保存时的默认文件名 */ async function downloadFileWithFetch(fileUrl, fileName) { try { // 1. 发起请求指定响应类型为blob const response await fetch(fileUrl); // 检查请求是否成功 if (!response.ok) { throw new Error(网络响应异常: ${response.status} ${response.statusText}); } // 2. 将响应体转换为Blob对象 const fileBlob await response.blob(); // 3. 为Blob创建临时的对象URL const objectUrl window.URL.createObjectURL(fileBlob); // 4. 创建隐藏的a标签触发下载 const link document.createElement(a); link.href objectUrl; link.download fileName || download; // 设置下载文件名 document.body.appendChild(link); // 部分浏览器需要元素在DOM中 link.click(); // 5. 清理移除元素并释放对象URL document.body.removeChild(link); window.URL.revokeObjectURL(objectUrl); console.log(文件 ${fileName} 下载已触发。); } catch (error) { // 统一的错误处理 console.error(文件下载失败:, error); // 这里可以替换为更友好的用户提示例如使用UI组件库的Message alert(下载失败: ${error.message}); } } // 使用示例 downloadFileWithFetch(https://api.example.com/reports/monthly.pdf, 2023年10月月报.pdf);这个函数有几个值得称道的细节健壮的错误处理使用try...catch包裹并检查response.ok能处理网络错误和服务器错误如404、500。内存管理下载触发后立即调用URL.revokeObjectURL()释放内存。对象URL会占用浏览器内存直到文档卸载或手动释放。兼容性考虑虽然fetch在现代浏览器中支持良好但在需要支持非常老旧浏览器如IE的项目中可能需要备用方案。2.2 方案二传统的XMLHttpRequest兼容性备选如果你的项目还需要考虑古老的浏览器环境比如某些内网系统XMLHttpRequest仍然是可靠的备选方案。它的逻辑与fetch类似但基于事件回调。function downloadFileWithXHR(fileUrl, fileName) { return new Promise((resolve, reject) { const xhr new XMLHttpRequest(); xhr.open(GET, fileUrl, true); xhr.responseType blob; // 关键指定期望的响应类型 xhr.onload function() { if (xhr.status 200) { const blob xhr.response; const objectUrl window.URL.createObjectURL(blob); const link document.createElement(a); link.href objectUrl; link.download fileName; link.click(); setTimeout(() { window.URL.revokeObjectURL(objectUrl); resolve(); }, 100); // 稍作延迟确保下载触发后再清理 } else { reject(new Error(请求失败状态码: ${xhr.status})); } }; xhr.onerror function() { reject(new Error(网络请求发生错误)); }; xhr.send(); }); }注意使用XMLHttpRequest时务必记得设置xhr.responseType blob否则你得到的将是文本或ArrayBuffer需要额外转换。2.3 方案对比与选择建议为了帮你快速决策我整理了两种核心方案的对比特性Fetch APIXMLHttpRequest语法基于Promise更现代简洁基于事件回调稍显繁琐流式处理原生支持响应流response.body适合大文件不支持一次性加载整个响应体默认携带Cookie默认不携带需设置credentials: include默认携带请求取消使用AbortController使用xhr.abort()浏览器支持现代浏览器完全支持IE完全不支持所有浏览器包括IE都支持推荐场景绝大多数现代Web应用需要兼容老旧浏览器如IE的项目我的建议很明确在新项目中毫不犹豫地选择fetch。代码更清晰功能更强大特别是流式处理而且是未来的标准。只有在维护必须兼容IE的遗留系统时才考虑XMLHttpRequest。3. 进阶技巧预览、分片与性能优化实现了基础下载后我们来看看更复杂的场景如何预览文件如何处理超大文件如何优化用户体验和性能3.1 实现文件预览功能预览的本质是将Blob转换为一个浏览器可以访问并渲染的URL。URL.createObjectURL(blob)生成的URL可以直接赋值给img、iframe、video或audio的src属性。/** * 预览图片Blob * param {Blob} imageBlob - 图片的Blob数据 * returns {string} - 对象URL使用后需释放 */ function previewImage(imageBlob) { const objectUrl URL.createObjectURL(imageBlob); const imgElement document.getElementById(preview-image); imgElement.src objectUrl; // 图片加载完成后可以释放URL对于预览通常等组件卸载时再释放 imgElement.onload function() { // URL.revokeObjectURL(objectUrl); // 谨慎使用立即释放会导致图片无法显示 }; return objectUrl; // 返回URL便于后续管理释放 } /** * 在iframe中预览PDF依赖浏览器内置PDF查看器 * param {Blob} pdfBlob - PDF文件的Blob数据 */ function previewPDF(pdfBlob) { const objectUrl URL.createObjectURL(pdfBlob); const iframe document.createElement(iframe); iframe.src objectUrl; iframe.style.width 100%; iframe.style.height 600px; iframe.title PDF预览; const container document.getElementById(preview-container); container.innerHTML ; // 清空旧内容 container.appendChild(iframe); // 当iframe卸载或预览关闭时需要释放URL // 可以将objectUrl存储在iframe元素的dataset中以便后续获取 iframe.dataset.objectUrl objectUrl; }关键陷阱内存管理。对象URL会一直占用内存直到页面关闭或你手动调用URL.revokeObjectURL()。对于需要长时间预览的内容如图片相册不要立即释放URL。最佳实践是在知道该URL不再需要时释放例如在Vue/React组件的beforeUnmount或useEffect清理函数中。3.2 处理大文件与分片下载当文件非常大比如几百MB的视频时一次性下载和创建Blob可能导致界面卡顿甚至内存溢出。这时可以考虑流式处理。fetchAPI的响应体response.body是一个ReadableStream我们可以分块读取和处理数据。下面的例子展示了如何实现一个带进度提示的大文件下载async function downloadLargeFileWithProgress(fileUrl, fileName) { const response await fetch(fileUrl); const contentLength response.headers.get(Content-Length); const total parseInt(contentLength, 10); if (!response.body) { throw new Error(响应体不可读); } const reader response.body.getReader(); let receivedLength 0; const chunks []; // 用于存储接收到的数据块 // 更新进度UI的函数假设页面上有一个id为progress的元素 const progressElement document.getElementById(download-progress); while(true) { const {done, value} await reader.read(); if (done) { break; } chunks.push(value); receivedLength value.length; // 更新进度 if (total) { const percent Math.round((receivedLength / total) * 100); progressElement.textContent ${percent}%; console.log(下载进度: ${percent}%); } } // 将所有分片合并成一个完整的Blob const blob new Blob(chunks); // ... 后续创建对象URL和触发下载的代码与之前相同 const objectUrl URL.createObjectURL(blob); triggerDownload(objectUrl, fileName); URL.revokeObjectURL(objectUrl); }这种方法在下载大文件时能提供更好的用户体验。你甚至可以在此基础上实现“断点续传”将已下载的分片信息存储到IndexedDB中。3.3 实战中的性能优化点并发下载限制如果页面需要同时下载多个文件不要无限制地发起并发请求。可以创建一个简单的下载队列控制同时进行的下载任务数量例如最多3个避免耗尽浏览器和服务器的资源。请求取消为用户提供取消下载的选项。使用AbortController可以优雅地中止fetch请求。const controller new AbortController(); const signal controller.signal; fetch(fileUrl, { signal }) .then(response response.blob()) .then(blob { /* ... */ }) .catch(err { if (err.name AbortError) { console.log(下载已被用户取消); } else { // 处理其他错误 } }); // 用户点击取消时调用 // controller.abort();Blob存储与复用如果同一个文件可能在页面生命周期内被多次使用如下载后又预览不要每次都重新请求。可以在第一次获取后将Blob对象或对象URL缓存起来。但要注意缓存策略和内存占用对于大文件需谨慎。服务端配合确保服务端在返回文件时设置了正确的响应头特别是Content-Type和Content-Disposition。Content-Disposition: attachment; filenamefile.pdf可以提示浏览器直接下载而inline则可能尝试预览。4. 避坑指南与最佳实践在项目里用了一段时间后我总结了一些容易踩坑的地方和对应的最佳实践希望能帮你少走弯路。4.1 常见问题与解决方案问题下载的文件名乱码或不正确。原因a标签的download属性对文件名编码支持有限且某些浏览器如旧版Edge、Safari有兼容性问题。此外如果文件是通过跨域请求获得的某些浏览器出于安全考虑会忽略download属性。解决方案确保文件名是简单的ASCII字符或使用encodeURIComponent处理。更可靠的方式是让后端在响应头Content-Disposition中指定文件名如attachment; filename*UTF-8${encodeURIComponent(filename)}前端从响应头中解析。对于跨域且无法控制服务端头部的场景可以尝试将Blob数据先保存到本地IndexedDB再通过第三方库如FileSaver.js触发下载兼容性更好。问题iOS Safari上下载行为异常。原因iOS Safari对程序触发的下载非用户直接点击限制非常严格。通过a.click()或window.open()触发下载经常无效对象URL也可能无法正常工作。解决方案对于iOS设备一个变通方案是在新窗口打开对象URL让用户手动长按保存。或者考虑引导用户使用其他浏览器。检测iOS并给出友好提示是一个不错的选择。问题Blob URL在控制台显示为blob:https://...如何调试这个URL是浏览器内存中的临时引用无法直接在地址栏访问或分享。要查看其内容你可以在Chrome DevTools的Network标签页中找到类型为blob的请求。或者将Blob对象通过FileReader读取为DataURLBase64格式这个字符串可以复制出来检查。4.2 安全与兼容性考量同源策略URL.createObjectURL()生成的URL遵循同源策略。这意味着来自不同源的Blob比如通过跨域请求获得的创建的URL在iframe或img中使用时可能会受到限制。确保你的文件资源CORS配置正确。内存泄漏这是使用对象URL时最容易被忽视也最严重的问题。每次调用createObjectURL都会创建一个新的URL映射占用内存。你必须成对地调用revokeObjectURL来释放。一个良好的模式是将对象URL与其使用它的DOM元素生命周期绑定。// 在Vue组件中的示例 export default { data() { return { imageUrl: null }; }, methods: { async loadImage() { const blob await fetchImage(); this.imageUrl URL.createObjectURL(blob); } }, beforeUnmount() { // 组件销毁前释放URL if (this.imageUrl) { URL.revokeObjectURL(this.imageUrl); } } };MIME类型嗅探如果创建Blob时未指定type或指定了错误的type如application/octet-stream浏览器会尝试“嗅探”内容来确定真实类型。这可能导致安全风险如一个恶意脚本被当作图片渲染或行为不一致。始终尽可能提供正确的MIME类型。4.3 封装一个健壮的下载工具函数最后结合上面所有的经验我们可以封装一个更健壮、功能更全面的下载工具函数。这个函数考虑了错误处理、进度提示、请求取消和基本的兼容性。class FileDownloader { constructor(options {}) { this.concurrentLimit options.concurrentLimit || 3; // 并发限制 this.downloadQueue []; this.activeCount 0; } /** * 主下载方法 * param {string} url - 文件地址 * param {string} filename - 文件名 * param {Object} options - 额外选项 { onProgress, signal } * returns {Promise} */ async download(url, filename, options {}) { const controller options.signal || new AbortController(); const signal controller.signal; return new Promise((resolve, reject) { const task { url, filename, options: { ...options, signal }, controller, resolve, reject, }; this.downloadQueue.push(task); this._processQueue(); }); } _processQueue() { while (this.activeCount this.concurrentLimit this.downloadQueue.length) { const task this.downloadQueue.shift(); this.activeCount; this._executeDownload(task).finally(() { this.activeCount--; this._processQueue(); }); } } async _executeDownload(task) { const { url, filename, options } task; const { onProgress, signal } options; try { const response await fetch(url, { signal }); if (!response.ok) throw new Error(HTTP ${response.status}); const blob await response.blob(); const objectUrl URL.createObjectURL(blob); const link document.createElement(a); link.href objectUrl; link.download filename; document.body.appendChild(link); link.click(); document.body.removeChild(link); // 延迟释放确保下载对话框已弹出 setTimeout(() URL.revokeObjectURL(objectUrl), 1000); task.resolve(); } catch (error) { if (error.name AbortError) { console.log(下载任务已取消: ${filename}); } else { console.error(下载失败 [${filename}]:, error); task.reject(error); } } } // 可以添加其他方法如暂停队列、清空队列等 } // 使用示例 const downloader new FileDownloader({ concurrentLimit: 2 }); downloader.download(/api/file/1, doc1.pdf, { onProgress: (percent) console.log(进度: ${percent}%) });这个类提供了简单的并发控制、基本的错误处理和可取消的下载任务。在实际项目中你可以根据需求进一步扩展比如添加重试机制、持久化队列到本地存储等。处理前端文件流从Blob到预览下载看似只是几个API的调用但细节决定体验。从正确设置MIME类型到严谨的内存管理再到应对各种浏览器的怪异行为每一步都需要仔细考量。我最开始也只会复制粘贴代码直到在线上环境遇到了iOS用户无法下载的投诉以及内存泄漏导致页面越来越卡的问题才真正重视起来。现在我会在项目初期就把文件下载/预览的工具函数封装好并写好单元测试这为后续开发节省了大量时间。记住对象URL用完后一定要释放对于大文件一定要考虑流式处理和进度反馈这些小事积累起来就是专业和业余的差别。

相关新闻

从AWR报告看Oracle内存配置:Shared Pool与Buffer Cache调优避坑指南

从AWR报告看Oracle内存配置:Shared Pool与Buffer Cache调优避坑指南

从AWR报告看Oracle内存配置:Shared Pool与Buffer Cache调优避坑指南 对于任何一位资深DBA而言,面对一个性能不佳的Oracle数据库,第一反应往往不是盲目地调整参数,而是打开AWR报告,像一位经验丰富的老中医一样“望闻问切…

2026/7/5 14:25:22 阅读更多 →
避坑指南:为什么你的PyTorch模型总在中期训练崩掉?可能是学习率调度器没选对!

避坑指南:为什么你的PyTorch模型总在中期训练崩掉?可能是学习率调度器没选对!

避坑指南:为什么你的PyTorch模型总在中期训练崩掉?可能是学习率调度器没选对! 你是否经历过这样的场景:模型训练初期一切顺利,损失曲线稳步下降,你满怀期待地泡了杯咖啡,准备迎接一个漂亮的收敛…

2026/7/4 1:31:08 阅读更多 →
Windows下用Conda一键搞定mayavi三维可视化环境(附PyQt5避坑指南)

Windows下用Conda一键搞定mayavi三维可视化环境(附PyQt5避坑指南)

Windows下用Conda一键搞定mayavi三维可视化环境(附PyQt5避坑指南) 三维数据可视化是数据科学和工程仿真中不可或缺的一环,它能将抽象的数字矩阵转化为直观的立体图像,帮助我们洞察数据背后的复杂模式与关系。对于在Windows平台上工…

2026/7/5 4:23:25 阅读更多 →

最新新闻

UI自动化测试实战指南:从原理到工具选型与Selenium项目搭建

UI自动化测试实战指南:从原理到工具选型与Selenium项目搭建

1. 从“点点点”到“自动跑”:UI自动化测试到底是什么? 如果你是一名软件测试工程师,或者正在学习软件测试,那么“UI自动化测试”这个词你一定不陌生。它听起来很高大上,似乎充满了技术感,但它的本质其实很…

2026/7/6 9:55:12 阅读更多 →
SpringBoot+Vue2办公系统源码包:含审批流、日志填报、会议室预约与RBAC权限控制

SpringBoot+Vue2办公系统源码包:含审批流、日志填报、会议室预约与RBAC权限控制

本文还有配套的精品资源,点击获取 简介:开箱即用的轻量级OA系统,后端用SpringBoot 2.x MyBatis MySQL,前端基于Vue 2.6 Element UI构建,适配毕业设计和中小团队内部管理场景。功能覆盖公告管理、文件收发与档案归…

2026/7/6 9:55:12 阅读更多 →
JMeter录制脚本全攻略:从零搭建性能测试自动化流水线

JMeter录制脚本全攻略:从零搭建性能测试自动化流水线

1. 项目概述:为什么录制脚本是性能测试的“临门一脚” 刚接触性能测试的新手,常常会卡在第一步:脚本怎么写?手动在JMeter里一个个添加HTTP请求,配置参数、头信息,不仅效率低下,还容易出错&#…

2026/7/6 9:53:09 阅读更多 →
从零搭建可私有化部署的AI Agent:Hermes三层记忆架构与实战指南

从零搭建可私有化部署的AI Agent:Hermes三层记忆架构与实战指南

🚀 30款热门AI模型一站整合,DeepSeek/GLM/Qwen 随心用,限时 5 折。 👉 点击领海量免费额度 最近在尝试将 AI Agent 从“玩具”升级为“生产力工具”时,发现了一个普遍痛点:很多教程要么停留在概念和 API…

2026/7/6 9:53:09 阅读更多 →
Python+Selenium UI自动化测试框架搭建:从PO模式到Pytest实战

Python+Selenium UI自动化测试框架搭建:从PO模式到Pytest实战

1. 项目概述与核心价值 最近在团队里做技术复盘,发现很多测试同学在尝试UI自动化时,总是一上来就埋头写脚本,结果代码越写越乱,维护成本高到离谱,最后项目不了了之。这让我想起几年前自己踩过的那些坑,所以…

2026/7/6 9:49:00 阅读更多 →
Kimi    LeetCode 3495. 使数组元素都变为零的最少操作次数 Rust实现

Kimi LeetCode 3495. 使数组元素都变为零的最少操作次数 Rust实现

这是 LeetCode 3495 的 Rust 实现。题目理解- 每个查询 [l, r] 定义数组 nums [l, l1, ..., r] - 每次操作选两个数 a, b,替换为 ⌊a/4⌋ 和 ⌊b/4⌋ - 求将所有元素变为 0 的最少操作次数核心思路一个数 x 变为 0 需要的操作次数是满足 4^p > x 的最小 p&#…

2026/7/6 9:49:00 阅读更多 →

日新闻

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/6 8:11:50 阅读更多 →
威胁模型全解析:从新手入门到实战应用,助你构建安全产品!

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

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

2026/7/6 8:11:52 阅读更多 →
渗透测试入门指南:从零基础到实战环境搭建

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

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

2026/7/6 6:52:56 阅读更多 →

月新闻