当前位置: 首页 > news >正文

Spring Boot | 基于MinIO实现文件上传和下载

关注:CodingTechWork

介绍

  在现代的 web 应用中,文件上传和下载是常见的需求。MinIO 是一个开源的高性能分布式对象存储服务,可以用来存储和管理大量的非结构化数据,如图片、视频、日志文件等。本文将介绍如何在 Spring Boot 应用中,结合 MinIO 来实现文件的上传和下载功能,并使用 Feign 客户端进行远程调用文件上传和下载的服务。

MinIO 相关介绍

  MinIO 是一个高性能的分布式对象存储系统,兼容 Amazon S3 API,通常用于存储和管理大量非结构化数据,如图片、视频、备份、日志等。它提供了与 S3 完全兼容的 API,使得开发者能够使用相同的工具和库与其进行交互。MinIO 被设计为云原生,适用于在 Docker、Kubernetes 和虚拟机中运行。

MinIO 特点

  1. 高性能:支持高吞吐量、高并发的读写操作,适用于需要大规模数据存储的应用。
  2. S3 兼容:MinIO 实现了完整的 Amazon S3 API,支持通过现有的 S3 客户端、SDK 和工具来进行交互。
  3. 高可扩展性:支持水平扩展,支持分布式部署,能够在多台机器上运行并提供统一的对象存储服务。
  4. 轻量级:MinIO 是一个轻量级的应用程序,易于部署和管理,可以在资源受限的环境中运行(如单机或者小型集群)。
  5. 支持对象加密:MinIO 支持对象级加密,可以为上传到存储中的对象加密,保证数据安全。
  6. 支持版本控制:MinIO 支持对象版本管理,允许对存储中的文件进行版本控制。

MinIO 核心概念

桶(Bucket)

  1. 在 MinIO 中,桶类似于文件系统中的文件夹。每个桶用于存储一组对象。
  2. 每个桶都可以有独立的权限配置。
  3. 存储在桶中的对象有唯一的标识符(通常是对象的文件名)。

对象(Object)

  1. 对象是 MinIO 存储的基本单位,类似于文件系统中的文件。
  2. 对象由数据和元数据组成,可以是任何类型的数据,如文本、图像、视频等。

对象键(Object Key)

  1. 对象键是对象在桶中的唯一标识符,通常对应于文件名。

访问密钥和密钥(Access Key & Secret Key)

  1. MinIO 使用访问密钥(Access Key)和密钥(Secret Key)进行身份验证,类似于 S3。
  2. 用户可以配置访问密钥和密钥以确保数据的访问权限。

MinIO API 介绍

  MinIO 的 API 设计遵循 S3 API,几乎所有 S3 的 API 都可以在 MinIO 中使用。以下是 MinIO 支持的常见操作和 API:

Bucket 操作

  1. 创建桶(Create Bucket):创建一个新桶来存储对象。
minioClient.makeBucket("mybucket");
  1. 列举桶(List Buckets):获取当前 MinIO 实例中所有存在的桶。
List<Bucket> buckets = minioClient.listBuckets();
  1. 检查桶是否存在(Bucket Exists):检查桶是否存在。
boolean exists = minioClient.bucketExists("mybucket");
  1. 删除桶(Delete Bucket):删除桶(桶必须为空才能删除)。
minioClient.removeBucket("mybucket");

对象操作

  1. 上传对象(Put Object):上传一个文件到 MinIO 中指定的桶。
minioClient.putObject("mybucket", "myfile.txt", fileInputStream, fileSize, null, null, "application/octet-stream");
  1. 获取对象(Get Object):从指定桶中获取对象内容。
InputStream inputStream = minioClient.getObject("mybucket", "myfile.txt");
  1. 删除对象(Remove Object):删除 MinIO 存储桶中的某个对象。
minioClient.removeObject("mybucket", "myfile.txt");
  1. 列举对象(List Objects):列举桶中的所有对象(可以按前缀过滤)。
Iterable<Result<Item>> objects = minioClient.listObjects("mybucket");
for (Result<Item> result : objects) {Item item = result.get();System.out.println("Object name: " + item.objectName());
}
  1. 获取对象元数据(Stat Object):获取对象的元数据,如大小、最后修改时间等。
StatObjectResponse stat = minioClient.statObject("mybucket", "myfile.txt");
System.out.println("Object size: " + stat.size());

文件下载

  1. 下载对象(Get Object):从 MinIO 中下载一个对象,并将其存储到本地文件系统。
minioClient.getObject("mybucket", "myfile.txt", Paths.get("/path/to/destination"));

对象版本控制

  1. 启用版本控制:启用桶的版本控制功能。
minioClient.enableBucketVersioning("mybucket");
  1. 获取对象版本(Get Object Version):获取对象的指定版本。
InputStream inputStream = minioClient.getObject("mybucket", "myfile.txt", "versionId");
  1. 删除对象版本(Remove Object Version):删除某个版本的对象。
minioClient.removeObject("mybucket", "myfile.txt", "versionId");

权限管理

  MinIO 支持基于用户的权限控制,可以通过配置桶的访问策略来管理谁可以访问存储中的对象。

  1. 设置桶的访问权限(Bucket Policy):设置桶的访问权限来限制用户对对象的访问。
String policy = "{ \"Version\": \"2025-01-07\", \"Statement\": [ { \"Effect\": \"Allow\", \"Principal\": { \"AWS\": \"*\" }, \"Action\": [ \"s3:GetObject\" ], \"Resource\": [ \"arn:aws:s3:::mybucket/*\" ] } ] }";
minioClient.setBucketPolicy("mybucket", policy);

MinIO 安全性特性

  1. 加密:
    MinIO 支持两种类型的加密:服务端加密(SSE)客户端加密(CSE)。服务端加密会在对象上传到 MinIO 时自动对其进行加密。
  2. 身份验证与授权:
    MinIO 使用访问密钥(Access Key)密钥(Secret Key)来进行身份验证。用户可以通过配置 MinIO 的访问控制列表(ACL)来限制谁可以访问桶和对象。
  3. TLS/SSL 支持:
    MinIO 支持通过 TLS(即 HTTPS)加密通信来保护数据传输安全。

项目结构

本项目的文件上传和下载功能将分成两个部分:

  1. minio 服务端(本地服务处理文件上传)
  2. Feign 客户端(模拟远程文件上传请求)
file-upload-demo
│
├── src/main/java/com/example/fileupload
│   ├── controller
│   │   └── FileController.java
│   ├── service
│   │   └── FileService.java
│   ├── feign
│   │   └── FileFeignClient.java
│   ├── FileUploadDemoApplication.java
│   └── ...
├── pom.xml
└── resources└── application.properties

Maven 依赖

在 pom.xml 中添加以下依赖:

<dependencies><!-- Spring Boot Web 依赖 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- Feign 依赖 --><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId></dependency><!-- minio 客户端依赖 --><dependency><groupId>io.minio</groupId><artifactId>minio</artifactId><version>8.3.5</version></dependency><!-- 文件上传需要的依赖 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-thymeleaf</artifactId></dependency>
</dependencies>

同时,在 application.properties 中配置文件上传大小限制:

properties配置文件

# MinIO 配置
minio.url=http://localhost:9000
minio.access-key=your-access-key
minio.secret-key=your-secret-key
minio.bucket-name=mybucket# 文件上传大小限制
spring.servlet.multipart.max-file-size=10MB
spring.servlet.multipart.max-request-size=10MB

代码示例

MinIO 配置

创建一个 MinIO 配置类来初始化 MinIO 客户端。
MinioConfig.java

package com.example.fileupload.config;import io.minio.MinioClient;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class MinioConfig {@Value("${minio.url}")private String minioUrl;@Value("${minio.access-key}")private String accessKey;@Value("${minio.secret-key}")private String secretKey;@Value("${minio.bucket-name}")private String bucketName;@Beanpublic MinioClient minioClient() {try {MinioClient minioClient = MinioClient.builder().endpoint(minioUrl).credentials(accessKey, secretKey).build();// 如果桶不存在则创建桶boolean isExist = minioClient.bucketExists(bucketName);if (!isExist) {minioClient.makeBucket(bucketName);}return minioClient;} catch (Exception e) {throw new RuntimeException("初始化 MinIO 客户端失败", e);}}
}

Controller 层:文件上传与下载接口

  在 Controller 层,我们定义文件上传和下载的接口。上传文件时将文件存储到 MinIO 中,下载文件时从 MinIO 拉取文件。
FileController.java

package com.example.fileupload.controller;import com.example.fileupload.service.FileService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.InputStreamResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;import java.io.IOException;@RestController
@RequestMapping("/api/files")
public class FileController {@Autowiredprivate FileService fileService;// 文件上传接口@PostMapping("/upload")public ResponseEntity<String> uploadFile(@RequestParam("file") MultipartFile file) {try {String fileUrl = fileService.uploadFile(file);return ResponseEntity.ok("文件上传成功: " + fileUrl);} catch (IOException e) {return ResponseEntity.status(500).body("文件上传失败: " + e.getMessage());}}// 文件下载接口@GetMapping("/download/{filename}")public ResponseEntity<InputStreamResource> downloadFile(@PathVariable String filename) {try {InputStreamResource resource = fileService.downloadFile(filename);return ResponseEntity.ok().header(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=" + filename).contentType(MediaType.APPLICATION_OCTET_STREAM).body(resource);} catch (IOException e) {return ResponseEntity.status(500).body(null);}}
}

Service 层:文件处理业务

  在 Service 层,我们定义实际的文件处理逻辑,包括文件上传和下载。我们使用 MultipartFile 来接收文件,并将其保存到服务器上。
FileService.java

package com.example.fileupload.service;import io.minio.MinioClient;
import io.minio.errors.MinioException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.InputStreamResource;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;import java.io.IOException;
import java.io.InputStream;@Service
public class FileService {@Autowiredprivate MinioClient minioClient;private final String bucketName = "mybucket";  // 从配置中加载桶名// 文件上传方法public String uploadFile(MultipartFile file) throws IOException {try {// 获取文件输入流InputStream fileInputStream = file.getInputStream();// 上传文件到 MinIOminioClient.putObject(bucketName, file.getOriginalFilename(), fileInputStream, file.getSize(), null, null, "application/octet-stream");return "http://localhost:9000/" + bucketName + "/" + file.getOriginalFilename();  // MinIO 文件 URL} catch (MinioException | IOException e) {throw new IOException("上传文件失败", e);}}// 文件下载方法public InputStreamResource downloadFile(String filename) throws IOException {try {// 获取文件输入流InputStream fileInputStream = minioClient.getObject(bucketName, filename);return new InputStreamResource(fileInputStream);} catch (MinioException | IOException e) {throw new IOException("下载文件失败", e);}}
}

Feign 客户端:远程调用文件上传下载服务

  Feign 是一个声明式的 HTTP 客户端,它简化了 HTTP 请求的调用过程。在这个例子中,我们使用 Feign 来调用远程的文件上传和下载接口。
FileFeignClient.java

package com.example.fileupload.feign;import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.*;@FeignClient(name = "file-upload-service", url = "http://localhost:8080/api/files")
public interface FileFeignClient {@PostMapping("/upload")String uploadFile(@RequestParam("file") MultipartFile file);@GetMapping("/download/{filename}")byte[] downloadFile(@PathVariable("filename") String filename);
}

Feign 使用示例

  在 Service 层,我们可以使用 Feign 客户端来调用远程的文件上传和下载接口。
FileService.java(使用 Feign 上传下载文件)

package com.example.fileupload.service;import com.example.fileupload.feign.FileFeignClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;@Service
public class FileService {@Autowiredprivate FileFeignClient fileFeignClient;// 使用 Feign 上传文件public String uploadFileViaFeign(MultipartFile file) {return fileFeignClient.uploadFile(file);}// 使用 Feign 下载文件public byte[] downloadFileViaFeign(String filename) {return fileFeignClient.downloadFile(filename);}
}

总结

  本文通过详细的代码示例,展示了如何将 MinIO 集成到 Spring Boot 中,来实现文件的上传和下载。通过 Feign 客户端的远程调用,可以将文件上传和下载的请求发送到远程服务中进行处理。

参考资料
Spring Boot 官方文档
Spring Cloud Feign 官方文档

相关文章:

Spring Boot | 基于MinIO实现文件上传和下载

关注&#xff1a;CodingTechWork 介绍 在现代的 web 应用中&#xff0c;文件上传和下载是常见的需求。MinIO 是一个开源的高性能分布式对象存储服务&#xff0c;可以用来存储和管理大量的非结构化数据&#xff0c;如图片、视频、日志文件等。本文将介绍如何在 Spring Boot 应用…...

企业手机号搜索API接口

每日免费每次消耗&#xff1a;按量每日限制&#xff1a;10 次每次请求积分消耗&#xff1a;50 积分 / 次总次数限制&#xff1a;10000 次每次请求间隔&#xff1a;0 秒&#xff0c;并发&#xff1a;50 请求地址 http(s)://api.aiqimao.com/index/apiphoneget/ 调试 请求方法…...

VirtualBox Main API 学习笔记

1. Philosophy 1.1 对于Python&#xff0c;推荐使用"WEBSERVICE"连接方式 Gemini 2.0 Flash Experimental: 对于 Java 和 Python&#xff1a; 文档建议您首先使用"WEBSERVICE"&#xff0c;因为它提供了一种更直观的方式来使用 API。 2. Configuration pi…...

[Linux]Mysql9.0.1服务端脱机安装配置教程(redhat)

前言 本教程适用于在yum源不可用的LInux主机上安装Mysql的场景。 以redhat系主机做操作示例&#xff0c;debian系主机可参照步骤&#xff0c;将对应的rpm -ivh命令换成dpkg -i。 1. 官网下载安装包 https://dev.mysql.com/downloads/mysql/ 1.1 版本分类 MySQL Enterprise…...

uniapp--HBuilder开发

提示&#xff1a;本文为学习内容&#xff0c;若有错误&#xff0c;请联系作者&#xff0c;谦虚受教。 文章目录 前言一、下载HBuilder二、添加modbus相关库1.下载nodejs2.下载modbus库3.项目添加modbus库 三、HBuilder相关功能语句1.文件夹说明2.消息信息框3.开关按钮4.选中按钮…...

计算机毕业设计学习项目-P10080 基于springboot+vue的社团管理系统的设计与实现

项目说明 本号所发布的项目均由我部署运行验证&#xff0c;可保证项目系统正常运行&#xff0c;以及提供完整源码。 如需要远程部署/定制/讲解系统&#xff0c;可以联系我。定制项目未经同意不会上传&#xff01; 项目源码获取方式放在文章末尾处 注&#xff1a;项目仅供学…...

with as提高sql的执行效率

实战sql with cte(UNIT_ID, UNIT_NAME, PARENT_UNIT_ID, UNIT_CODE ) as (select UNIT_ID, UNIT_NAME, PARENT_UNIT_ID , UNIT_CODEfrom HPFM_UNITunion allselect t.UNIT_ID, t.UNIT_NAME, t.PARENT_UNIT_ID, t.UNIT_CODEfrom HPFM_UNIT tjoin cte on t.PARENT_UNIT_ID cte.U…...

【银河麒麟高级服务器操作系统实例】tcp半链接数溢出分析及处理全过程

了解更多银河麒麟操作系统全新产品&#xff0c;请点击访问 麒麟软件产品专区&#xff1a;https://product.kylinos.cn 开发者专区&#xff1a;https://developer.kylinos.cn 文档中心&#xff1a;https://document.kylinos.cn 服务器环境以及配置 系统环境 物理机/虚拟机/云…...

计算机毕业设计Python中华古诗词知识图谱可视化 古诗词智能问答系统 古诗词数据分析 古诗词情感分析模型 自然语言处理NLP 机器学习 深度学习

温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 作者简介&#xff1a;Java领…...

分布式ID生成-雪花算法实现无状态

雪花算法这里不再赘述&#xff0c;其缺点是有状态&#xff08;多副本隔离时&#xff0c;依赖手动配置workId和datacenterId&#xff09;&#xff0c;代码如下&#xff1a; /*** 雪花算法ID生成器*/ public class SnowflakeIdWorker {/*** 开始时间截 (2017-01-01)*/private st…...

【问题】配置 Conda 与 Pip 源

通常情况下,使用 conda 命令或者 pip 命令都是从国外的服务器上下载需要的模块包的,这在网速不佳的情况下会消耗大量的时间。所以这里建议更换国内的源来进行模块下载,速度会大大提升。 具体方法如下: 打开命令行 cmd 工具,输入以下命令。 ① Conda 换源 conda config…...

Zookeeper是如何保证事务的顺序一致性的?

大家好&#xff0c;我是锋哥。今天分享关于【Zookeeper是如何保证事务的顺序一致性的?】面试题。希望对大家有帮助&#xff1b; Zookeeper是如何保证事务的顺序一致性的? 1000道 互联网大厂Java工程师 精选面试题-Java资源分享网 Zookeeper 通过多个机制来保证事务的顺序一…...

东土科技参股广汽集团飞行汽车初创公司,为低空经济构建新型产业生态

近日&#xff0c;广汽集团旗下专注于飞行汽车领域的初创公司广东高域科技有限公司于2024年12月31日正式成立&#xff0c;在穿透后的股东信息中&#xff0c;东土科技通过广州瓴云科技投资合伙企业&#xff08;有限合伙&#xff09;赫然在列。 此前12月18日&#xff0c;广汽集团…...

Oracle 中的各种名称(*_name)参数的含义与作用

Oracle 中的各种名称&#xff08;*_name&#xff09;参数的含义与作用 目录 Oracle 中的各种名称&#xff08;*_name&#xff09;参数的含义与作用一、数据库名&#xff1a;db_name二、数据库所在的域&#xff1a;db_domain三、全局数据库名&#xff1a;global_name四、服务名&…...

前端页面的内容格式

TaskBuilder可以编辑的前端页面类型分为HTML和tfp&#xff08;Taskmsg Front Page&#xff09;两种格式&#xff0c;HTML格式只能用代码编辑器编辑&#xff0c;这种模式基本很少有人用&#xff0c;大家都用tfp格式&#xff0c;因为使用TaskBuilder向导创建的前端页面都是采用的…...

数据库1-4讲

各种名词区分 内模式也叫物理模式、存储模式。 概念模式也叫全局模式、逻辑模式。 外模式也叫用户模式。 笛卡尔积&#xff1a;D1、D2、D3集合中任取一个的所有可能情况。 因此上述笛卡尔积的基数22312 关系模型的三个完整性&#xff1a; 实体完整性&#x…...

设计模式 行为型 命令模式(Command Pattern)与 常见技术框架应用 解析

命令模式&#xff08;Command Pattern&#xff09;是一种行为型设计模式&#xff0c;它旨在将请求发送者和接收者解耦&#xff0c;通过将一个请求封装为一个对象&#xff0c;从而允许参数化客户端对象以进行不同的请求、排队请求或记录请求&#xff0c;并支持可撤销操作。 在软…...

【Redis】简介|优点|使用场景|为什么Redis快

目录 一、简介 二、特性&#xff08;优点&#xff09; 三、使用场景 一、简介 内存中存储数据的中间件&#xff0c;用于数据库&#xff0c;数据缓存&#xff0c;在分布式系统中能够大展拳脚 中间件&#xff1a;应用程序可以直接从 Redis 中获取数据&#xff0c;而不必频繁地…...

Clisoft SOS与CAD系统集成

Clisoft SOS与CAD系统集成 以下内容大部分来自官方文档&#xff0c;目前只用到与Cadence Virtuoso集成&#xff0c;其他还未用到&#xff0c;如有问题或相关建议&#xff0c;可以留言。 与Keysight ADS集成 更新SOS客户端配置文件sos.cfg&#xff0c;以包含支持ADS的模板&am…...

【linux系统之redis6】redis的安装与初始化

下载redis的linux对应的安装包&#xff0c;并上传到linux虚拟机里面 解压压缩包 tar -zxzf redis-6.2.6.tar.gz解压后&#xff0c;进入redis文件 cd redis-6.2.6执行编译 make && make install看到下图&#xff0c;就说明redis安装成功了 默认的安装路径&#xff0c…...

MPNet:旋转机械轻量化故障诊断模型详解python代码复现

目录 一、问题背景与挑战 二、MPNet核心架构 2.1 多分支特征融合模块(MBFM) 2.2 残差注意力金字塔模块(RAPM) 2.2.1 空间金字塔注意力(SPA) 2.2.2 金字塔残差块(PRBlock) 2.3 分类器设计 三、关键技术突破 3.1 多尺度特征融合 3.2 轻量化设计策略 3.3 抗噪声…...

vscode里如何用git

打开vs终端执行如下&#xff1a; 1 初始化 Git 仓库&#xff08;如果尚未初始化&#xff09; git init 2 添加文件到 Git 仓库 git add . 3 使用 git commit 命令来提交你的更改。确保在提交时加上一个有用的消息。 git commit -m "备注信息" 4 …...

DAY 47

三、通道注意力 3.1 通道注意力的定义 # 新增&#xff1a;通道注意力模块&#xff08;SE模块&#xff09; class ChannelAttention(nn.Module):"""通道注意力模块(Squeeze-and-Excitation)"""def __init__(self, in_channels, reduction_rat…...

前端导出带有合并单元格的列表

// 导出async function exportExcel(fileName "共识调整.xlsx") {// 所有数据const exportData await getAllMainData();// 表头内容let fitstTitleList [];const secondTitleList [];allColumns.value.forEach(column > {if (!column.children) {fitstTitleL…...

将对透视变换后的图像使用Otsu进行阈值化,来分离黑色和白色像素。这句话中的Otsu是什么意思?

Otsu 是一种自动阈值化方法&#xff0c;用于将图像分割为前景和背景。它通过最小化图像的类内方差或等价地最大化类间方差来选择最佳阈值。这种方法特别适用于图像的二值化处理&#xff0c;能够自动确定一个阈值&#xff0c;将图像中的像素分为黑色和白色两类。 Otsu 方法的原…...

oracle与MySQL数据库之间数据同步的技术要点

Oracle与MySQL数据库之间的数据同步是一个涉及多个技术要点的复杂任务。由于Oracle和MySQL的架构差异&#xff0c;它们的数据同步要求既要保持数据的准确性和一致性&#xff0c;又要处理好性能问题。以下是一些主要的技术要点&#xff1a; 数据结构差异 数据类型差异&#xff…...

【JavaWeb】Docker项目部署

引言 之前学习了Linux操作系统的常见命令&#xff0c;在Linux上安装软件&#xff0c;以及如何在Linux上部署一个单体项目&#xff0c;大多数同学都会有相同的感受&#xff0c;那就是麻烦。 核心体现在三点&#xff1a; 命令太多了&#xff0c;记不住 软件安装包名字复杂&…...

全志A40i android7.1 调试信息打印串口由uart0改为uart3

一&#xff0c;概述 1. 目的 将调试信息打印串口由uart0改为uart3。 2. 版本信息 Uboot版本&#xff1a;2014.07&#xff1b; Kernel版本&#xff1a;Linux-3.10&#xff1b; 二&#xff0c;Uboot 1. sys_config.fex改动 使能uart3(TX:PH00 RX:PH01)&#xff0c;并让boo…...

在Mathematica中实现Newton-Raphson迭代的收敛时间算法(一般三次多项式)

考察一般的三次多项式&#xff0c;以r为参数&#xff1a; p[z_, r_] : z^3 (r - 1) z - r; roots[r_] : z /. Solve[p[z, r] 0, z]&#xff1b; 此多项式的根为&#xff1a; 尽管看起来这个多项式是特殊的&#xff0c;其实一般的三次多项式都是可以通过线性变换化为这个形式…...

消防一体化安全管控平台:构建消防“一张图”和APP统一管理

在城市的某个角落&#xff0c;一场突如其来的火灾打破了平静。熊熊烈火迅速蔓延&#xff0c;滚滚浓烟弥漫开来&#xff0c;周围群众的生命财产安全受到严重威胁。就在这千钧一发之际&#xff0c;消防救援队伍迅速行动&#xff0c;而豪越科技消防一体化安全管控平台构建的消防“…...