Swagger3文件上传实战:Spring Boot中MultipartFile与JSON元数据混合提交指南
1. 混合提交为什么文件上传总让人头疼做后端开发的朋友尤其是刚接触Spring Boot和Swagger的朋友估计都遇到过这个场景前端要上传一个文件比如用户头像同时还要带上这个文件的描述信息比如“这是张三的证件照”。你心想这还不简单一个MultipartFile接收文件再来一个String接收描述搞定结果一对接前端同学跑过来说“接口调不通啊Swagger里怎么让我填字符串不是传文件” 或者更糟文件传上来了但那个描述信息的JSON对象死活接收不到后台日志里报了一堆类型转换错误。我刚开始做项目的时候也在这个坑里摔过好几次。最典型的一次是做一个内容管理系统的素材上传接口要求同时上传图片文件和图片的元数据标题、标签、分类ID。我按“常规”思路写了接口自测用Postman传得好好的结果前端一集成要么文件传了元数据丢了要么Swagger文档里显示得乱七八糟根本没法用。后来才发现问题就出在内容类型Content-Type的冲突上。简单来说当你的请求体里同时有文件multipart/form-data和JSON数据时Spring和Swagger这对“好兄弟”有时候会闹别扭。Spring期望文件部分用multipart/form-data格式而JSON部分如果你用RequestBody注解它又期望是application/json。一个请求怎么能有两种Content-Type呢这就矛盾了。Swagger3特别是基于OpenAPI 3.0规范的springdoc-openapi在生成API文档时如果没配置好它可能无法正确识别MultipartFile参数把它当成普通的String类型来显示导致文档里出现一个文本输入框而不是文件选择按钮这显然不是我们想要的。所以这篇文章要解决的就是这个“混合提交”的难题。我会手把手带你在Spring Boot项目里用Swagger3清晰地定义一个接口让它既能漂亮地接收文件又能完整地接收结构化的JSON元数据。无论你是刚入门的新手还是被这个问题困扰了一阵子的朋友跟着我的步骤走保证你能把这个功能稳稳当当地实现并且让前后端协作变得无比顺畅。我们不止要解决功能问题还要让API文档清晰、易用这才是现代开发的正确姿势。2. 环境搭建与基础配置工欲善其事必先利其器。在开始写代码之前我们得先把项目架子搭好把必要的依赖引进来。这里我假设你已经有了一个基础的Spring Boot项目如果没有可以去 start.spring.io 快速生成一个记得选上Spring Web依赖。2.1 引入关键依赖对于Swagger3我们使用目前社区最主流的springdoc-openapi套件。它完美支持OpenAPI 3.0规范而且配置起来比老旧的springfox要简单直观得多。在你的pom.xml文件里添加以下依赖dependency groupIdorg.springdoc/groupId artifactIdspringdoc-openapi-ui/artifactId version1.7.0/version !-- 请使用当时的最新稳定版 -- /dependency dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-web/artifactId /dependency第一个依赖springdoc-openapi-ui是关键它会自动引入Swagger UI的界面以及核心的注解解析库。第二个spring-web是Spring Boot的Web基础处理HTTP请求和文件上传都靠它。加完依赖启动你的应用然后访问http://localhost:8080/swagger-ui.html你应该就能看到Swagger的漂亮界面了如果端口是8080的话。如果没看到别急可能还需要一点简单配置。2.2 基础Swagger配置虽然springdoc号称零配置但为了更符合我们项目的风格通常我们会创建一个配置类。在项目的配置包下比如com.yourproject.config新建一个SwaggerConfig类import io.swagger.v3.oas.models.OpenAPI; import io.swagger.v3.oas.models.info.Info; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; Configuration public class SwaggerConfig { Bean public OpenAPI customOpenAPI() { return new OpenAPI() .info(new Info() .title(文件上传与元数据混合提交API文档) .version(1.0) .description(演示如何同时处理文件上传和JSON元数据)); } }这个配置非常简单就是定义了一下我们API文档的标题、版本和描述。springdoc会自动扫描项目中的RestController等注解生成对应的API信息。到这里一个支持Swagger3的基础Spring Boot环境就准备好了。你可能注意到这里并没有像一些老教程里那样配置Docketbean那是因为springdoc的配置方式更现代化直接用OpenAPI这个对象。接下来我们就可以进入核心的控制器编写环节了。3. 核心实现混合提交接口的三种写法准备好了基础环境我们来攻克最核心的部分如何编写这个混合提交的接口。根据我的经验主要有三种写法各有优劣适用于不同的场景。我会从最简单但问题最多的写法开始带你一步步优化到最推荐的生产级写法。3.1 错误示范为什么 RequestParam 行不通很多朋友的第一反应可能是这样写因为看起来最直观PostMapping(/upload-simple) public String uploadSimple(RequestParam(file) MultipartFile file, RequestParam(metadata) String metadataJson) { // 手动解析 metadataJson 字符串为对象 // ... 业务逻辑 return 上传成功; }这种写法在Swagger UI里file参数可能会错误地显示为一个文本输入框类型为string而不是文件选择器。为什么呢因为RequestParam注解默认用于处理application/x-www-form-urlencoded或multipart/form-data中的简单字段。当Swagger试图为MultipartFile类型生成文档时如果没有明确指定其媒体类型它可能无法推断出这是一个文件参数。更麻烦的是这里的metadataJson是一个String类型前端需要手动将JSON对象JSON.stringify()成字符串传过来后端再手动用ObjectMapper解析非常不优雅也容易出错。3.2 正确入门使用 RequestPart 注解为了解决上述问题Spring提供了RequestPart注解。这个注解专门用于处理multipart/form-data请求中的“部分”part它能更好地与内容类型协商配合。改进后的写法如下import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; RestController RequestMapping(/api/files) public class FileUploadController { Operation(summary 上传文件基础版) PostMapping(value /upload-basic, consumes MediaType.MULTIPART_FORM_DATA_VALUE) public ResponseEntityString uploadBasic( Parameter(description 上传的文件) RequestPart(file) MultipartFile file, Parameter(description 文件元数据JSON字符串) RequestPart(metadata) String metadata) { // 仍然需要手动解析 metadata 字符串 try { ObjectMapper mapper new ObjectMapper(); FileMetadata meta mapper.readValue(metadata, FileMetadata.class); // 处理文件和元数据... return ResponseEntity.ok(文件与元数据接收成功); } catch (JsonProcessingException e) { return ResponseEntity.badRequest().body(元数据JSON格式错误); } } }关键点分析consumes MediaType.MULTIPART_FORM_DATA_VALUE这个属性在PostMapping注解中至关重要。它明确告诉Spring和Swagger这个接口只消费multipart/form-data类型的请求。这是让Swagger UI正确显示文件上传控件的关键一步。RequestPart用这个注解替代RequestParam来标注file参数。RequestPart会考虑每个部分的Content-Type头信息虽然对于文件部分通常是application/octet-stream或具体的文件类型但使用这个注解是更规范的做法。Swagger注解我们使用了Operation来描述接口用Parameter来描述参数这样生成的文档会更清晰。这个版本已经比第一个好多了至少在Swagger UI里file参数有很大概率能正确显示为文件上传组件。但是metadata参数仍然是个字符串我们需要在业务代码里进行JSON解析这不够“Spring风格”。我们的目标是让Spring自动帮我们把JSON字符串反序列化成Java对象。3.3 进阶方案自动绑定JSON对象这才是我们理想的解决方案让metadata参数直接是一个自定义的Java对象Spring自动完成绑定。这里需要一点小技巧因为默认情况下Spring的HttpMessageConverter不会去处理RequestPart标注的非文件参数。我们需要确保我们的对象能被正确反序列化。首先定义一个元数据类import lombok.Data; // 使用Lombok简化代码 Data public class FileMetadata { private String title; private String description; private String category; private ListString tags; // 其他字段... // 记得生成getter/setter或用Lombok的 Data 注解 }然后修改我们的控制器方法Operation(summary 上传文件推荐版) PostMapping(value /upload, consumes MediaType.MULTIPART_FORM_DATA_VALUE) public ResponseEntityUploadResponse uploadFile( Parameter(description 上传的文件) RequestPart(file) MultipartFile file, Parameter(description 文件元数据) RequestPart(metadata) FileMetadata metadata) { // 现在 metadata 已经是 FileMetadata 对象了 log.info(收到文件: {}, 大小: {} bytes, file.getOriginalFilename(), file.getSize()); log.info(元数据: 标题-{}, 分类-{}, metadata.getTitle(), metadata.getCategory()); // 你的业务逻辑例如保存文件将元数据存入数据库等 String fileUrl storageService.save(file); String fileId metadataService.save(metadata, fileUrl); UploadResponse response new UploadResponse(fileId, fileUrl, 上传成功); return ResponseEntity.ok(response); }如何让Spring自动转换的关键在于前端发送请求时必须为metadata这个part设置正确的Content-Type头。当使用FormData对象在JavaScript中构建请求时你需要这样做const formData new FormData(); formData.append(file, fileInput.files[0]); // 文件part const meta { title: 我的文件, description: ... }; // 重要将JSON对象转换为Blob并指定Content-Type const metadataBlob new Blob([JSON.stringify(meta)], { type: application/json }); formData.append(metadata, metadataBlob); // 元数据part // 然后使用axios或fetch发送formData当Spring接收到这个请求发现metadata部分的Content-Type是application/json并且你的方法参数类型是FileMetadata它就会尝试使用配置好的HttpMessageConverter默认的MappingJackson2HttpMessageConverter来将请求体中的JSON数据转换为对象。这样我们就实现了文件二进制和复杂JSON对象结构化数据在同一个multipart/form-data请求中的完美混合提交。在Swagger UI中这两个参数也会被清晰地展示出来file是文件类型metadata会是一个JSON对象的示例编辑器体验非常好。4. Swagger3文档的精细化配置接口写好了但如果Swagger文档看起来不专业或者测试起来不方便那这个接口就算不上完美。特别是对于混合类型接口Swagger的默认展示可能还需要我们微调一下才能达到最佳效果。4.1 使用 Schema 注解美化元数据模型上面的FileMetadata类在Swagger文档里可能只显示属性名和类型。我们可以用Schema注解来增加描述甚至提供示例值让前端开发者一目了然。import io.swagger.v3.oas.annotations.media.Schema; Data public class FileMetadata { Schema(description 文件的标题, example 季度报告.pdf, requiredMode Schema.RequiredMode.REQUIRED) private String title; Schema(description 文件的详细描述, example 这是2023年第四季度的财务分析报告) private String description; Schema(description 文件所属分类, example 财务文档) private String category; Schema(description 文件标签列表, example [\重要\, \内部\]) private ListString tags; }这样配置后在Swagger UI的“Schemas”部分FileMetadata模型会显示这些友好的描述和示例。在接口的“Try it out”区域当你编辑metadata参数时它会预填这些示例值大大提升了测试的便利性。4.2 处理文件参数的特殊显示对于MultipartFile类型的参数springdoc通常能很好地识别并渲染为文件上传组件。但有时你可能想给它加个描述或者指定它是必选的。我们可以通过Parameter注解来实现Operation(summary 上传文件完整文档版) PostMapping(value /upload, consumes MediaType.MULTIPART_FORM_DATA_VALUE) public ResponseEntityUploadResponse uploadFile( Parameter(description 请选择要上传的文件, required true, content Content(mediaType MediaType.APPLICATION_OCTET_STREAM_VALUE)) // 这个content有时可省略 RequestPart(file) MultipartFile file, Parameter(description 文件的描述性元数据需为JSON格式) RequestPart(metadata) FileMetadata metadata) { // ... }这里Parameter的content属性可以用来进一步指定这个参数的媒体类型虽然对于文件上传Swagger UI通常能自动处理但在某些复杂场景下指定一下会更保险。重点是required true和清晰的description能让API使用者明确知道这个参数是必须的。4.3 全局配置忽略 MultipartFile 的模型展开这是一个非常实用的小技巧。如果你在Swagger的模型列表里看到了MultipartFile这个类被展开里面显示一堆像bytes、resource这样的内部属性可能会觉得有点干扰。我们可以通过配置让springdoc在生成文档时忽略MultipartFile这个类型的模型展开。在你的application.yml或application.properties中添加springdoc: api-docs: resolve-schema-properties: true swagger-ui: disable-swagger-default-url: true packages-to-scan: com.yourproject.controller paths-to-match: /api/**更精细的控制可以在配置类中通过OpenAPI自定义构建器实现但通常上述配置加上正确的注解就足够了。经过这些配置你的Swagger文档界面将会非常清晰接口说明明确参数要求一目了然metadata有漂亮的JSON示例file是标准的文件上传按钮。前后端开发同学基于这份文档进行协作效率会高很多。5. 实战中的坑与解决方案理论很美好但现实往往会在你意想不到的地方给你挖个坑。下面这几个问题都是我或者我身边的同事在实际项目中真真切切遇到过的我把它们和解决方案一起分享给你希望能帮你省下不少调试时间。5.1 坑一Swagger UI中文件参数显示为String这是最常见的问题。现象是代码明明写的是MultipartFile但Swagger UI里对应的参数输入框是个文本框不是文件选择器。原因与解决方案缺少consumes属性这是最主要的原因。务必在PostMapping或RequestMapping注解中明确指定consumes MediaType.MULTIPART_FORM_DATA_VALUE。这相当于给Swagger一个明确的信号“我这个接口是吃multipart/form-data格式的饭的”。错误使用了RequestParam如前所述对于文件上传尤其是在混合类型请求中使用RequestPart比RequestParam更准确、更安全。将注解替换掉试试。依赖冲突或版本问题确保你使用的是较新且稳定的springdoc-openapi-ui版本如1.6.x或1.7.x。老版本或某些有冲突的依赖可能会影响注解的解析。5.2 坑二JSON元数据无法自动转换为对象现象文件能收到但metadata参数接收到的永远是null或者后台抛出HttpMessageNotReadableException异常提示无法将String转换为FileMetadata。原因与解决方案前端未设置正确的 Content-Type这是根本原因。当前端使用FormData附加JSON对象时必须将其转换为Blob或String并显式设置该部分的Content-Type头为application/json。参考前面JavaScript代码示例中的Blob用法。如果用的是axios它会自动处理吗对于FormDataaxios默认不会为每个part单独设置Content-Type所以最好手动处理。缺少无参构造函数或Setter你的FileMetadata类必须有一个公共的无参数构造函数默认就有但如果你定义了带参构造记得补上无参构造并且各个字段要有公共的setter方法如果用Lombok的Data就自动生成了。因为Spring是通过反射调用无参构造创建对象再用setter方法注入属性的。使用RequestBody注解千万不要在混合请求的参数上使用RequestBody。RequestBody意味着整个请求体是一个单一的JSON这与multipart/form-data格式是冲突的。坚持使用RequestPart。5.3 坑三文件大小限制与请求超时当上传大文件时你可能会遇到MaxUploadSizeExceededException或者连接超时。解决方案在application.yml中配置spring: servlet: multipart: max-file-size: 10MB # 单个文件最大大小 max-request-size: 100MB # 整个请求最大大小 enabled: true这两个配置项非常重要需要根据你的实际业务需求进行调整。比如做视频上传可能就需要设置为几百MB甚至上GB。另外对于超长时间的上传可能还需要在Web服务器如Tomcat或网关层面调整连接超时和读取超时的设置。5.4 坑四多文件与多组元数据混合上传业务场景有时会更复杂比如一个相册一次上传多张图片每张图片还有独立的描述。这怎么处理解决方案使用数组或列表接收。PostMapping(value /upload-multiple, consumes MediaType.MULTIPART_FORM_DATA_VALUE) public ResponseEntityString uploadMultiple( RequestPart(files) MultipartFile[] files, RequestPart(metadatas) FileMetadata[] metadatas) { // 注意files 和 metadatas 数组需要顺序对应 // 或者更常见的做法是前端用一个文件对应一个元数据对象组成一个part }但更优雅的做法是定义一个包装类把单个文件和其元数据绑定在一起然后用一个列表接收这个包装类。不过这就需要前端构造数据时做一些调整或者后端用一个更灵活的结构比如MapString, String来接收动态的元数据。处理多文件混合上传时关键是要和前端约定好数据格式是并行数组还是嵌套结构并在Swagger文档中写清楚。6. 完整可运行的示例项目光说不练假把式我准备了一个最简化的、可立即运行的控制器示例包含了异常处理、日志记录和基本的响应封装。你可以把这个代码复制到你的项目里稍作修改比如文件存储路径就能跑起来。import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.responses.ApiResponses; import lombok.extern.slf4j.Slf4j; import javax.validation.Valid; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.UUID; Slf4j RestController RequestMapping(/api/v1/files) public class FileUploadController { // 定义一个简单的存储目录生产环境请用更专业的方案如OSS、S3 private static final String UPLOAD_DIR ./uploads/; Operation(summary 上传文件及其元数据, description 接收一个文件和一个对应的JSON格式元数据对象) ApiResponses(value { ApiResponse(responseCode 200, description 上传成功), ApiResponse(responseCode 400, description 请求参数或格式错误, content Content(schema Schema(implementation ErrorResponse.class))), ApiResponse(responseCode 500, description 服务器内部错误, content Content(schema Schema(implementation ErrorResponse.class))) }) PostMapping(value /upload, consumes MediaType.MULTIPART_FORM_DATA_VALUE) public ResponseEntityUploadResult uploadFileAndMetadata( Parameter(description 要上传的二进制文件, required true) RequestPart(file) MultipartFile file, Parameter(description 文件的元数据信息) Valid RequestPart(value metadata, required false) FileMetadata metadata) { // 1. 基础校验 if (file.isEmpty()) { throw new IllegalArgumentException(上传的文件不能为空); } // 2. 生成唯一文件名防止覆盖 String originalFilename file.getOriginalFilename(); String fileExtension originalFilename.substring(originalFilename.lastIndexOf(.)); String savedFilename UUID.randomUUID().toString() fileExtension; Path destinationPath Paths.get(UPLOAD_DIR, savedFilename); try { // 3. 确保上传目录存在 Files.createDirectories(destinationPath.getParent()); // 4. 保存文件到本地 file.transferTo(destinationPath.toFile()); log.info(文件保存成功: {}, destinationPath.toAbsolutePath()); // 5. 处理元数据 (这里只是打印实际应存入数据库) if (metadata ! null) { log.info(接收到元数据 - 标题: {}, 描述: {}, metadata.getTitle(), metadata.getDescription()); // 可以将 metadata 和 savedFilename 关联起来存入数据库 } else { log.warn(本次上传未提供元数据); } // 6. 构造成功响应 UploadResult result new UploadResult(); result.setSuccess(true); result.setMessage(文件上传成功); result.setFilename(savedFilename); result.setOriginalFilename(originalFilename); result.setFileSize(file.getSize()); result.setMetadata(metadata); // 假设我们有一个能访问文件的URL前缀 result.setUrl(/uploads/ savedFilename); return ResponseEntity.ok(result); } catch (IOException e) { log.error(文件保存失败, e); throw new RuntimeException(文件保存过程中发生错误, e); } } // 简单的响应DTO Data Schema(description 文件上传结果) public static class UploadResult { private boolean success; private String message; private String filename; private String originalFilename; private Long fileSize; private FileMetadata metadata; private String url; } // 错误响应DTO Data public static class ErrorResponse { private String timestamp; private int status; private String error; private String message; private String path; } }这个示例包含了以下几个关键实践清晰的API文档使用了Operation,ApiResponses等注解生成了完善的接口文档包括成功和错误的响应模型。参数校验对上传的文件进行了非空检查并对元数据对象使用了Valid注解如果FileMetadata内部有NotBlank等校验注解则会生效。业务逻辑演示了如何安全地保存文件使用UUID重命名并记录了元数据。异常处理虽然示例中直接抛出了运行时异常但在生产环境中你应该使用ControllerAdvice编写全局异常处理器将不同类型的异常转换为结构化的错误响应如上面的ErrorResponse返回给前端。结构化响应使用了一个UploadResult对象作为响应体包含了上传结果的所有关键信息便于前端处理。把这个控制器放进你的Spring Boot项目启动应用打开http://localhost:8080/swagger-ui.html找到/api/v1/files/upload这个接口你就可以直接在上面测试文件上传和元数据提交了。记得先在项目根目录下创建一个uploads文件夹或者修改UPLOAD_DIR为你想要的路径。通过这个完整的例子你应该能彻底掌握在Spring Boot中利用Swagger3处理混合类型文件上传的精髓了。

相关新闻

PETRV2-BEV模型训练:新手也能轻松掌握的教程

PETRV2-BEV模型训练:新手也能轻松掌握的教程

PETRV2-BEV模型训练:新手也能轻松掌握的教程 你是不是对自动驾驶里的“鸟瞰图”技术感到好奇?想自己动手训练一个能看懂周围环境的AI模型,但又觉得步骤太复杂,不知道从哪开始? 别担心,这篇教程就是为你准…

2026/7/5 4:23:12 阅读更多 →
LLaVA-1.6-7B性能优化:降低显存占用的小技巧

LLaVA-1.6-7B性能优化:降低显存占用的小技巧

LLaVA-1.6-7B性能优化:降低显存占用的小技巧 1. 引言:为什么需要显存优化? 当你使用LLaVA-1.6-7B进行多模态推理时,是否遇到过显存不足的问题?这个强大的视觉语言模型虽然功能出色,但对显存的需求也相当可…

2026/7/4 21:17:27 阅读更多 →
5分钟搞定:用llava-v1.6-7b搭建智能客服原型

5分钟搞定:用llava-v1.6-7b搭建智能客服原型

5分钟搞定:用llava-v1.6-7b搭建智能客服原型 1. 引言:为什么选择LLaVA做智能客服? 想象一下这样的场景:用户给你的客服发来一张产品图片,问"这个怎么用?"或者"这个零件叫什么?…

2026/7/4 21:18:36 阅读更多 →

最新新闻

零日漏洞攻防实战:从检测到响应的纵深防御体系构建

零日漏洞攻防实战:从检测到响应的纵深防御体系构建

1. 项目概述:直面数字世界的“隐形杀手”在网络安全这个没有硝烟的战场上,最让防御者感到棘手的,往往不是那些已知的、有补丁可循的威胁,而是那些被称为“零日漏洞”的未知攻击。从业十几年,我处理过无数次安全事件&am…

2026/7/5 13:16:07 阅读更多 →
多人聊天室

多人聊天室

一、项目简介本项目是一个基于Java Swing MySQL的博客文章管理系统,实现了文章发布、分类管理、用户登录、全局搜索等核心功能。 我在项目中主要负责全局搜索模块、数据库读写层设计以及部分面向对象架构设计工作。二、个人任务简述序号完成功能与任务描述1全局搜索…

2026/7/5 13:14:06 阅读更多 →
骑乘无忧怎么选 (新手女生小个子巡航摩托)选购要点

骑乘无忧怎么选 (新手女生小个子巡航摩托)选购要点

入手自动挡巡航摩托,CVT 和 AMT 该怎么选?面向入门骑手、女性车友以及身高娇小的人群,最优方案已然明确。AMT 巡航操控顺手、动力充沛、使用便捷,外观也十分出彩,是综合实力更强的选择。QJMOTOR 闪 300AMT 与闪 400AMT…

2026/7/5 13:14:06 阅读更多 →
Azure Local离线模式采购(系列篇之七)

Azure Local离线模式采购(系列篇之七)

0. 重要定位(先看清 Acquire 在做什么) ⚠️ Acquire ≠ 部署完成。Acquire 阶段仅完成 Azure 资源创建及部署介质获取,Virtual Appliance 尚未部署到本地数据中心。完整的生命周期是: Acquire → Deploy → Configure → Operate…

2026/7/5 13:12:06 阅读更多 →
杭州老板IP打造运营公司怎么选?

杭州老板IP打造运营公司怎么选?

选择杭州的老板IP打造运营公司时,可以从以下几个方面进行考量:一、明确需求与目标核心需求:首先明确你希望通过IP打造实现什么目的。是增加品牌知名度、提升客户信任度,还是直接促进销售转化? 行业特性:根据…

2026/7/5 13:12:06 阅读更多 →
input_report_key + input_sync:按键事件的正确报告姿势

input_report_key + input_sync:按键事件的正确报告姿势

input_report_key input_sync:按键事件的正确报告姿势这个仓库已经开源!所有教程,主线内核移植,跑新版本imx-linux/uboot都在这里,或者一起来尝试跑7.1的Linux!欢迎各位大佬观摩!喜欢的话点个⭐…

2026/7/5 13:10:06 阅读更多 →

日新闻

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 阅读更多 →

周新闻

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 阅读更多 →

月新闻