项目实战--Spring Boot + Minio文件切片上传下载

1.搭建环境

引入项目依赖

<!-- 操作minio的java客户端-->
<dependency><groupId>io.minio</groupId><artifactId>minio</artifactId><version>8.5.2</version>
</dependency>
<!--        jwt鉴权相应依赖-->
<dependency><groupId>ch.qos.logback</groupId><artifactId>logback-classic</artifactId><version>1.2.3</version>
</dependency>
<dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt-jackson</artifactId><version>0.11.2</version>
</dependency>

创建容器桶
在这里插入图片描述
在这里插入图片描述
获取API访问凭证
在这里插入图片描述
在这里插入图片描述
编写配置文件

server:port: 8080
spring:servlet:multipart:max-file-size: 10MBmax-request-size: 10MB#minio配置minio:access-key: dAMaxkWaXUD1CV1JHbqwsecret-key: AXt3SD0JFkDENFbMeJKOOQb5wj8KvabZWu33Rs84url: http://192.168.128.114:9090  #访问地址bucket-name: wx_manager
首先是服务器的配置:端口号为8080,用于监听请求。使用了一个Servlet来处理multipart/form-data类型的请求。在接收到multipart/form-data类型的请求时,会将上传的文件大小限制在10MB以内,并将请求大小限制在10MB以内。接下来是minio的配置:access-key和secret-key是访问minio服务的凭证,需要根据实际情况进行填写。url是minio服务的地址,需要根据实际情况进行填写。bucket-name是存储文件的桶名,需要根据实际情况进行填写。

http请求状态

public class HttpStatus
{/*** 操作成功*/public static final int SUCCESS = 200;/*** 对象创建成功*/public static final int CREATED = 201;/*** 请求已经被接受*/public static final int ACCEPTED = 202;/*** 操作已经执行成功,但是没有返回数据*/public static final int NO_CONTENT = 204;/*** 资源已被移除*/public static final int MOVED_PERM = 301;/*** 重定向*/public static final int SEE_OTHER = 303;/*** 资源没有被修改*/public static final int NOT_MODIFIED = 304;/*** 参数列表错误(缺少,格式不匹配)*/public static final int BAD_REQUEST = 400;/*** 未授权*/public static final int UNAUTHORIZED = 401;/*** 访问受限,授权过期*/public static final int FORBIDDEN = 403;/*** 资源,服务未找到*/public static final int NOT_FOUND = 404;/*** 不允许的http方法*/public static final int BAD_METHOD = 405;/*** 资源冲突,或者资源被锁*/public static final int CONFLICT = 409;/*** 不支持的数据,媒体类型*/public static final int UNSUPPORTED_TYPE = 415;/*** 系统内部错误*/public static final int ERROR = 500;/*** 接口未实现*/public static final int NOT_IMPLEMENTED = 501;/*** 系统警告消息*/public static final int WARN = 601;
}

通用常量信息

import io.jsonwebtoken.Claims;public class Constants
{/*** UTF-8 字符集*/public static final String UTF8 = "UTF-8";/*** GBK 字符集*/public static final String GBK = "GBK";/*** www主域*/public static final String WWW = "www.";/*** http请求*/public static final String HTTP = "http://";/*** https请求*/public static final String HTTPS = "https://";/*** 通用成功标识*/public static final String SUCCESS = "0";/*** 通用失败标识*/public static final String FAIL = "1";/*** 登录成功*/public static final String LOGIN_SUCCESS = "Success";/*** 注销*/public static final String LOGOUT = "Logout";/*** 注册*/public static final String REGISTER = "Register";/*** 登录失败*/public static final String LOGIN_FAIL = "Error";/*** 验证码有效期(分钟)*/public static final Integer CAPTCHA_EXPIRATION = 2;/*** 令牌*/public static final String TOKEN = "token";/*** 令牌前缀*/public static final String TOKEN_PREFIX = "Bearer ";/*** 令牌前缀*/public static final String LOGIN_USER_KEY = "login_user_key";/*** 用户ID*/public static final String JWT_USERID = "userid";/*** 用户名称*/public static final String JWT_USERNAME = Claims.SUBJECT;/*** 用户头像*/public static final String JWT_AVATAR = "avatar";/*** 创建时间*/public static final String JWT_CREATED = "created";/*** 用户权限*/public static final String JWT_AUTHORITIES = "authorities";/*** 资源映射路径 前缀*/public static final String RESOURCE_PREFIX = "/profile";/*** RMI 远程方法调用*/public static final String LOOKUP_RMI = "rmi:";/*** LDAP 远程方法调用*/public static final String LOOKUP_LDAP = "ldap:";/*** LDAPS 远程方法调用*/public static final String LOOKUP_LDAPS = "ldaps:";/*** 定时任务白名单配置(仅允许访问的包名,如其他需要可以自行添加)*/public static final String[] JOB_WHITELIST_STR = { "com.ruoyi" };/*** 定时任务违规的字符*/public static final String[] JOB_ERROR_STR = { "java.net.URL", "javax.naming.InitialContext", "org.yaml.snakeyaml","org.springframework", "org.apache", "com.ruoyi.common.utils.file", "com.ruoyi.common.config" };
}

Minio的配置类

import io.minio.MinioClient;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Data
@Configuration
@ConfigurationProperties(prefix = "spring.minio")
public class MinioConfig {// 访问密钥和密钥值private String accessKey;private String secretKey;private String url;private String bucketName;@Beanpublic MinioClient minioClient(){return MinioClient.builder().endpoint(url).credentials(accessKey,secretKey).build();}
}

Minio的工具类

import com.xiaohui.config.MinioConfig;
import io.minio.*;
import io.minio.errors.*;
import io.minio.http.Method;
import lombok.SneakyThrows;
import org.apache.tomcat.util.http.fileupload.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.time.ZonedDateTime;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;/*** @Description Minio工具类*/@Component
public class MinioUtils {@Autowiredprivate MinioClient minioClient;@Autowiredprivate MinioConfig configuration;/*** @param name 名字* @return boolean* @Description description: 判断bucket是否存在,不存在则创建*/public boolean existBucket(String name) {boolean exists;try {exists = minioClient.bucketExists(BucketExistsArgs.builder().bucket(name).build());if (!exists) {minioClient.makeBucket(MakeBucketArgs.builder().bucket(name).build());exists = true;}} catch (Exception e) {e.printStackTrace();exists = false;}return exists;}/*** @param bucketName 存储bucket名称* @return {@link Boolean }* @Description 创建存储bucket*/public Boolean makeBucket(String bucketName) {try {minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());} catch (Exception e) {e.printStackTrace();return false;}return true;}/*** @param bucketName 存储bucket名称* @return {@link Boolean }* @Description 删除存储bucket* @Author IT小辉同学* @Date 2023/06/02*/public Boolean removeBucket(String bucketName) {try {minioClient.removeBucket(RemoveBucketArgs.builder().bucket(bucketName).build());} catch (Exception e) {e.printStackTrace();return false;}return true;}/*** @param fileName 文件名称* @param time     时间* @return {@link Map }* @Description 获取上传临时签名*/@SneakyThrowspublic Map getPolicy(String fileName, ZonedDateTime time) {PostPolicy postPolicy = new PostPolicy(configuration.getBucketName(), time);postPolicy.addEqualsCondition("key", fileName);try {Map<String, String> map = minioClient.getPresignedPostFormData(postPolicy);HashMap<String, String> map1 = new HashMap<>();map.forEach((k, v) -> {map1.put(k.replaceAll("-", ""), v);});map1.put("host", configuration.getUrl() + "/" + configuration.getBucketName());return map1;} catch (ErrorResponseException e) {e.printStackTrace();} catch (InsufficientDataException e) {e.printStackTrace();} catch (InternalException e) {e.printStackTrace();} catch (InvalidKeyException e) {e.printStackTrace();} catch (InvalidResponseException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();} catch (NoSuchAlgorithmException e) {e.printStackTrace();} catch (ServerException e) {e.printStackTrace();} catch (XmlParserException e) {e.printStackTrace();}return null;}/*** @param objectName 对象名称* @param method     方法* @param time       时间* @param timeUnit   时间单位* @return {@link String }* @Description 获取上传文件的url*/public String getPolicyUrl(String objectName, Method method, int time, TimeUnit timeUnit) {try {return minioClient.getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder().method(method).bucket(configuration.getBucketName()).object(objectName).expiry(time, timeUnit).build());} catch (ErrorResponseException e) {e.printStackTrace();} catch (InsufficientDataException e) {e.printStackTrace();} catch (InternalException e) {e.printStackTrace();} catch (InvalidKeyException e) {e.printStackTrace();} catch (InvalidResponseException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();} catch (NoSuchAlgorithmException e) {e.printStackTrace();} catch (XmlParserException e) {e.printStackTrace();} catch (ServerException e) {e.printStackTrace();}return null;}/*** @param file     文件* @param fileName 文件名称* @Description 上传文件*/public void upload(MultipartFile file, String fileName) {// 使用putObject上传一个文件到存储桶中。try {InputStream inputStream = file.getInputStream();minioClient.putObject(PutObjectArgs.builder().bucket(configuration.getBucketName()).object(fileName).stream(inputStream, file.getSize(), -1).contentType(file.getContentType()).build());} catch (ErrorResponseException e) {e.printStackTrace();} catch (InsufficientDataException e) {e.printStackTrace();} catch (InternalException e) {e.printStackTrace();} catch (InvalidKeyException e) {e.printStackTrace();} catch (InvalidResponseException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();} catch (NoSuchAlgorithmException e) {e.printStackTrace();} catch (ServerException e) {e.printStackTrace();} catch (XmlParserException e) {e.printStackTrace();}}/*** @param objectName 对象名称* @param time       时间* @param timeUnit   时间单位* @return {@link String }* @Description 根据filename获取文件访问地址*/public String getUrl(String objectName, int time, TimeUnit timeUnit) {String url = null;try {url = minioClient.getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder().method(Method.GET).bucket(configuration.getBucketName()).object(objectName).expiry(time, timeUnit).build());} catch (ErrorResponseException e) {e.printStackTrace();} catch (InsufficientDataException e) {e.printStackTrace();} catch (InternalException e) {e.printStackTrace();} catch (InvalidKeyException e) {e.printStackTrace();} catch (InvalidResponseException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();} catch (NoSuchAlgorithmException e) {e.printStackTrace();} catch (XmlParserException e) {e.printStackTrace();} catch (ServerException e) {e.printStackTrace();}return url;}/*** @param fileName* @return {@link ResponseEntity }<{@link byte[] }>* @Description description: 下载文件*/public ResponseEntity<byte[]> download(String fileName) {ResponseEntity<byte[]> responseEntity = null;InputStream in = null;ByteArrayOutputStream out = null;try {in = minioClient.getObject(GetObjectArgs.builder().bucket(configuration.getBucketName()).object(fileName).build());out = new ByteArrayOutputStream();IOUtils.copy(in, out);//封装返回值byte[] bytes = out.toByteArray();HttpHeaders headers = new HttpHeaders();try {headers.add("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));} catch (UnsupportedEncodingException e) {e.printStackTrace();}headers.setContentLength(bytes.length);headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);headers.setAccessControlExposeHeaders(Arrays.asList("*"));responseEntity = new ResponseEntity<byte[]>(bytes, headers, HttpStatus.SUCCESS);} catch (Exception e) {e.printStackTrace();} finally {try {if (in != null) {try {in.close();} catch (IOException e) {e.printStackTrace();}}if (out != null) {out.close();}} catch (IOException e) {e.printStackTrace();}}return responseEntity;}/*** @param objectFile 对象文件* @return {@link String }* @Description 根据文件名和桶获取文件路径*/public String getFileUrl(String objectFile) {try {return minioClient.getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder().method(Method.GET).bucket(configuration.getBucketName()).object(objectFile).build());} catch (Exception e) {e.printStackTrace();}return null;}
}
使用阿里云的对象存储服务(OSS)进行文件上传和下载:getPolicy(String fileName, ZonedDateTime time):根据文件名和时间戳获取上传临时签名。getPolicyUrl(String objectName, Method method, int time, TimeUnit timeUnit):获取上传文件的url。upload(MultipartFile file, String fileName):将文件上传到OSS中。getUrl(String objectName, int time, TimeUnit timeUnit):获取文件的下载url。使用枚举类型来定义不同的上传和下载方法。使用了注解@Autowired来自动注入MinioClient对象。该工具类没有提供异常处理机制,需要根据实际情况进行补充。

Ajax请求工具类

/*** @Description ajax结果*/
public class AjaxResult extends HashMap<String, Object>
{private static final long serialVersionUID = 1L;/** 状态码 */public static final String CODE_TAG = "code";/** 返回内容 */public static final String MSG_TAG = "msg";/** 数据对象 */public static final String DATA_TAG = "data";/*** 初始化一个新创建的 AjaxResult 对象,使其表示一个空消息。*/public AjaxResult(){}/*** 初始化一个新创建的 AjaxResult 对象** @param code 状态码* @param msg 返回内容*/public AjaxResult(int code, String msg){super.put(CODE_TAG, code);super.put(MSG_TAG, msg);}/*** 初始化一个新创建的 AjaxResult 对象** @param code 状态码* @param msg 返回内容* @param data 数据对象*/public AjaxResult(int code, String msg, Object data){super.put(CODE_TAG, code);super.put(MSG_TAG, msg);if (data!=null){super.put(DATA_TAG, data);}}/*** 返回成功消息** @return 成功消息*/public static AjaxResult success(){return AjaxResult.success("操作成功");}/*** 返回成功数据** @return 成功消息*/public static AjaxResult success(Object data){return AjaxResult.success("操作成功", data);}/*** 返回成功消息** @param msg 返回内容* @return 成功消息*/public static AjaxResult success(String msg){return AjaxResult.success(msg, null);}/*** 返回成功消息** @param msg 返回内容* @param data 数据对象* @return 成功消息*/public static AjaxResult success(String msg, Object data){return new AjaxResult(HttpStatus.SUCCESS, msg, data);}/*** 返回警告消息** @param msg 返回内容* @return 警告消息*/public static AjaxResult warn(String msg){return AjaxResult.warn(msg, null);}/*** 返回警告消息** @param msg 返回内容* @param data 数据对象* @return 警告消息*/public static AjaxResult warn(String msg, Object data){return new AjaxResult(HttpStatus.WARN, msg, data);}/*** 返回错误消息** @return 错误消息*/public static AjaxResult error(){return AjaxResult.error("操作失败");}/*** 返回错误消息** @param msg 返回内容* @return 错误消息*/public static AjaxResult error(String msg){return AjaxResult.error(msg, null);}/*** 返回错误消息** @param msg 返回内容* @param data 数据对象* @return 错误消息*/public static AjaxResult error(String msg, Object data){return new AjaxResult(HttpStatus.ERROR, msg, data);}/*** 返回错误消息** @param code 状态码* @param msg 返回内容* @return 错误消息*/public static AjaxResult error(int code, String msg){return new AjaxResult(code, msg, null);}/*** 方便链式调用** @param key 键* @param value 值* @return 数据对象*/@Overridepublic AjaxResult put(String key, Object value){super.put(key, value);return this;}
}

Minio文件操作接口层

import com.xiaohui.utils.AjaxResult;
import com.xiaohui.utils.MinioUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;import java.util.HashMap;/*** @Description minio文件上传控制器*/
@CrossOrigin
@RestController
@RequestMapping("/api")
public class MinioFileUploadController {@Autowiredprivate MinioUtils minioUtils;/*** @param file     文件* @param fileName 文件名称* @return {@link AjaxResult }* @Description 上传文件*/@GetMapping("/upload")public AjaxResult uploadFile(@RequestParam("file") MultipartFile file, String fileName) {minioUtils.upload(file, fileName);return AjaxResult.success("上传成功");}/*** @param fileName 文件名称* @return {@link ResponseEntity }* @Description dowload文件*/@GetMapping("/dowload")public ResponseEntity dowloadFile(@RequestParam("fileName") String fileName) {return minioUtils.download(fileName);}/*** @param fileName 文件名称* @return {@link AjaxResult }* @Description 得到文件url*/@GetMapping("/getUrl")public AjaxResult getFileUrl(@RequestParam("fileName") String fileName){HashMap map=new HashMap();map.put("FileUrl",minioUtils.getFileUrl(fileName));return AjaxResult.success(map);}
}
2.测试

Minio大文件上传
在这里插入图片描述
在这里插入图片描述
Minio大文件地址
在这里插入图片描述

访问这个地址即可。

参考文档
Centos7安装Minio笔记

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Python + OpenCV 开启图片、写入储存图片

这篇教学会介绍OpenCV 里imread()、imshow()、waitKey() 方法&#xff0c;透过这些方法&#xff0c;在电脑中使用不同的色彩模式开启图片并显示图片。 imread() 开启图片 使用imread() 方法&#xff0c;可以开启图片&#xff0c;imread() 有两个参数&#xff0c;第一个参数为档…

[c++] 可变参数模版

前言 可变参数模板是C11及之后才开始使用,学校的老古董编译器不一定能用 相信大家在刚入门c/c时都接触过printf函数 int printf ( const char * format, ... ); printf用于将数据格式化输出到屏幕上,它的参数非常有意思,可以支持任意数量,任意类型的多参数.而如果我们想实现类…

陶建辉当选 GDOS 全球数据库及开源峰会荣誉顾问

近日&#xff0c;第二十三届 GOPS 全球运维大会暨 XOps 技术创新峰会在北京正式召开。本次会议重点议题方向包括开源数据库落地思考、金融数据库自主可控、云原生时代下数据库、数据库智能运维、数据库安全与隐私、开源数据库与治理。大会深入探讨这些方向&#xff0c;促进了数…

方法引用详解

什么是方法引用&#xff1f;&#xff1a;针对于函数式接口中的抽象方法 为什么用方法引用&#xff1f;&#xff1a;避免代码的重复&#xff0c;简便书写&#xff0c;提高效率 在使用Lambda表达式的时候&#xff0c;我们实际上传递进去的代码就是一种解决方案&#xff1a;拿参数…

服务器数据恢复—raid5阵列硬盘出现大量坏道的数据恢复案例

服务器存储数据恢复环境&故障&#xff1a; 一台DELL EqualLogic PS 4000存储中有一组由12块磁盘组建的raid5阵列&#xff0c;存储空间划分3个同等大小的卷&#xff0c;采用的VMFS文件系统。 两块硬盘指示灯亮黄色&#xff0c;raid5阵列崩溃&#xff0c;存储变得不可用。 服…

代码随想录——划分字母区间(Leetcode763)

题目链接 贪心 class Solution {public List<Integer> partitionLabels(String s) {int[] count new int[27];Arrays.fill(count,0);// 统计元素最后一次出现的位置for(int i 0; i < s.length(); i){count[s.charAt(i) - a] i;}List<Integer> res new Ar…

mac怎么压缩pdf文件大小,mac压缩pdf文件大小不改变清晰度

在数字化时代&#xff0c;pdf格式因其良好的兼容性和稳定性&#xff0c;成为了文档分享和传输的首选。然而&#xff0c;随着文件内容的丰富&#xff0c;pdf文件的体积也越来越大&#xff0c;给存储和传输带来了不小的困扰。本文将揭秘几种简单有效的pdf文件压缩方法&#xff0c…

多粒度封锁-封锁粒度、多粒度封锁模式

一、引言 1、若采用封锁技术实现并发控制&#xff0c;事务在访问数据库对象前要在数据库对象上加锁&#xff0c;为提高事务的并发程度&#xff0c;商用DBMS会采用一种多粒度封锁方法 2、事务可访问的数据库对象可以是逻辑单元&#xff0c;包括关系、关系中的元组、关系的属性…

【C++】map和set详解

目录 1. 关联式容器 2. 键值对pair 3. 树形结构的关联式容器 4. set 4.1 set的介绍 4.2 set的构造 4.3 set的迭代器 4.4 set的容量 4.5 set的常用函数 5. multiset 6. map 6.1 map的介绍 6.2 map的构造 6.3 map的迭代器 6.4 map的容量 6.5 map的operator[] 6.6…

Python入门 2024/7/6

目录 元组的定义和操作 字符串的定义和操作 字符串 字符串的替换 字符串的分割 字符串的规整操作&#xff08;去除前后空格&#xff09; 字符串的规整操作&#xff08;去掉前后指定字符串&#xff09; 操作 字符串的替换 字符串的分割 字符串的规整操作 统计字符串的…

ESP32——物联网小项目汇总

商品级ESP32智能手表 [文章链接] 用ESP32&#xff0c;做了个siri&#xff1f;&#xff01;开源了&#xff01; [文章链接]

JSP WEB开发(一) JSP语言基础

目录 JSP JSP简介&#xff1a; JSP页面 JSP运行原理 JSP脚本元素 JAVA程序片 局部变量 全局变量和方法的声明 全局变量 方法的声明 程序片执行特点 synchronized关键字 表达式 JSP指令标记 page指令 include指令 JSP动作标记 JSP动作元素include和include指令的…

测试环境:使用OpenSSL生成证书并配置Https

文章目录 需求1、安装OpenSSL1.1、安装包下载1.2、安装&#xff08;以window 64位为例&#xff09;1.3、配置环境变量&#xff08;非必须&#xff09; 2、生成证书2.1、新建文件夹2.2、生成根证书2.2.1、生成私钥2.2.2、生成根证书&#xff0c;并且自签名 2.3、服务端证书生成2…

前端根据目录生成模块化路由routes

根据约定大于配置的逻辑&#xff0c;如果目录结构约定俗成&#xff0c;前端是可以根据目录结构动态生成路由所需要的 route 结构的&#xff0c;这个过程是要在编译时 进行&#xff0c;生成需要的代码&#xff0c;保证运行时的代码正确即可 主流的打包工具都有对应的方法读取文…

设计模式之状态机模式

一、状态机模式介绍 状态机模式&#xff08;State Machine Pattern&#xff09;是一种用于描述对象行为的软件设计模式&#xff0c;属于行为型设计模式。在状态机模式中&#xff0c;对象的行为取决于其内部状态&#xff0c;并且在不同的状态下&#xff0c;对象可能会有不同的行…

Java信号量semaphore的原理与使用方法

Semaphore的基本概念 在Java中&#xff0c;Semaphore是位于java.util.concurrent包下的一个类。它的核心就是维护了一个许可集。简单来说&#xff0c;就是有一定数量的许可&#xff0c;线程需要先获取到许可&#xff0c;才能执行&#xff0c;执行完毕后再释放许可。 那么&…

Unity 简单载具路线 Waypoint 导航

前言 在游戏开发和导航系统中&#xff0c;"waypoint" 是指路径中的一个特定位置或点。它通常用于定义一个物体或角色在场景中移动的目标位置或路径的一部分。通过一系列的 waypoints&#xff0c;可以指定复杂的移动路径和行为。以下是一些 waypoint 的具体用途&…

YoloV8改进策略:Block改进|轻量实时的重参数结构|最新改进|即插即用(全网首发)

摘要 本文使用重参数的Block替换YoloV8中的Bottleneck&#xff0c;GFLOPs从165降到了116&#xff0c;降低了三分之一&#xff1b;同时&#xff0c;map50-95从0.937涨到了0.947。 改进方法简单&#xff0c;只做简单的替换就行&#xff0c;即插即用&#xff0c;非常推荐&#xf…

【leetcode52-55图论、56-63回溯】

图论 回溯【56-63】 46.全排列 class Solution:def permute(self, nums):result []self.backtracking(nums, [], [False] * len(nums), result)return resultdef backtracking(self, nums, path, used, result):if len(path) len(nums):result.append(path[:])returnfor i …

pdf怎么转换成图片格式文件,pdf文档怎么转换成图片格式

在数字化时代&#xff0c;pdf文件转换成图片格式是一种常见的操作&#xff0c;无论是在工作还是日常生活中&#xff0c;我们总会遇到需要将pdf文件转换为图片的需求。这可能是因为图片格式更易于分享、展示或编辑。那么&#xff0c;如何高效地将pdf转换成图片呢&#xff1f;本文…