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

SpringBoot整合minio

SpringBoot整合minio

  • 1. 下载及安装
    • 1.1 windows版本
    • 1.2 Linux版本
  • 2. SpringBoot整合minio
    • 2.1 依赖
    • 2.2 配置文件
    • 2.3 配置类
    • 2.4 工具类
    • 2.5 测试
    • 1. 业务层
      • 2. 控制层

1. 下载及安装

1.1 windows版本

目录结构
在这里插入图片描述

启动文件
在这里插入图片描述
在这里插入图片描述
标红的地方按实际安装地更改

@echo off
REM 声明采用UTF-8编码
chcp 65001
echo.
echo [信息] 运行MinIO文服务器。
echo.
:: 设置窗口标题
title Minio文件服务:: 设置用户名为myname
setx MINIO_ROOT_USER minio
:: 设置密码为mypassword
setx MINIO_ROOT_PASSWORD minio123cd %~dp0
:: 切换到minio.exe文件所在目录
cd D:\dev\minio\bin
:: 启动minio服务
minio.exe server D:\dev\minio\data --console-address ":9001" --address ":9000" > D:\dev\minio\logs\minio.log
pause

1.2 Linux版本

待更新

2. SpringBoot整合minio

2.1 依赖

        <dependency><groupId>io.minio</groupId><artifactId>minio</artifactId><version>8.2.1</version><exclusions><exclusion><groupId>com.squareup.okhttp3</groupId><artifactId>okhttp</artifactId></exclusion><exclusion><groupId>org.jetbrains.kotlin</groupId><artifactId>kotlin-stdlib</artifactId></exclusion></exclusions></dependency><dependency><groupId>com.squareup.okhttp3</groupId><artifactId>okhttp</artifactId><version>4.9.0</version></dependency>

2.2 配置文件

minio:url: http://127.0.0.1:9000 #Minio服务所在地址bucketName: zld #存储桶名称accessKey: minio #访问的keysecretKey: minio123 #访问的秘钥

2.3 配置类

package com.ruoyi.minio.config;import io.minio.MinioClient;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
@ConfigurationProperties(prefix = "minio")
public class MinioConfig {/*** minio服务器地址*/private String url;/*** 用户名*/private String accessKey;/*** 密码*/private String secretKey;/*** 密码*/private String bucketName;public String getUrl() {return url;}public void setUrl(String url) {this.url = url;}public String getAccessKey() {return accessKey;}public void setAccessKey(String accessKey) {this.accessKey = accessKey;}public String getSecretKey() {return secretKey;}public void setSecretKey(String secretKey) {this.secretKey = secretKey;}public String getBucketName() {return bucketName;}public void setBucketName(String bucketName) {this.bucketName = bucketName;}@Beanpublic MinioClient minioClient() {return MinioClient.builder().endpoint(url).credentials(accessKey, secretKey).build();}
}

2.4 工具类

package com.ruoyi.minio.util;import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.spring.SpringUtils;
import com.ruoyi.common.utils.uuid.IdUtils;
import com.ruoyi.minio.config.MinioConfig;
import io.minio.*;
import io.minio.errors.*;
import io.minio.http.Method;
import io.minio.messages.Bucket;
import io.minio.messages.DeleteError;
import io.minio.messages.Item;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.FastByteArrayOutputStream;
import org.springframework.web.multipart.MultipartFile;import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;@Component
public class MinioUtil {@Autowiredprivate MinioConfig prop;@Resourceprivate MinioClient minioClient;/*** 查看存储bucket是否存在** @return boolean*/public Boolean bucketExists(String bucketName) {Boolean found;try {found = minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());} catch (Exception e) {e.printStackTrace();return false;}return found;}/*** 创建存储bucket** @return Boolean*/public Boolean makeBucket(String bucketName) {try {minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());} catch (Exception e) {e.printStackTrace();return false;}return true;}/*** 删除存储bucket** @return Boolean*/public Boolean removeBucket(String bucketName) {try {minioClient.removeBucket(RemoveBucketArgs.builder().bucket(bucketName).build());} catch (Exception e) {e.printStackTrace();return false;}return true;}/*** 获取全部bucket*/public List<Bucket> getAllBuckets() {try {List<Bucket> buckets = minioClient.listBuckets();return buckets;} catch (Exception e) {e.printStackTrace();}return null;}/*** 文件上传** @param file 文件* @return Boolean*/public String upload(MultipartFile file) {String originalFilename = file.getOriginalFilename();if (StringUtils.isBlank(originalFilename)) {throw new RuntimeException();}String fileName = IdUtils.simpleUUID() + originalFilename.substring(originalFilename.lastIndexOf("."));String objectName = DateUtils.datePath() + "/" + fileName;try {PutObjectArgs objectArgs = PutObjectArgs.builder().bucket(prop.getBucketName()).object(objectName).stream(file.getInputStream(), file.getSize(), -1).contentType(file.getContentType()).build();//文件名称相同会覆盖minioClient.putObject(objectArgs);} catch (Exception e) {e.printStackTrace();return null;}return objectName;}/*** 文件上传** @param bucketName* @param fileName* @param multipartFile* @return* @throws IOException*/public String uploadFile(String bucketName, String fileName, MultipartFile multipartFile) throws IOException {String url = "";MinioClient minioClient = SpringUtils.getBean(MinioClient.class);try (InputStream inputStream = multipartFile.getInputStream()) {boolean found = minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());if (!found) {minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());/*** bucket权限-读写*/String READ_WRITE = "{\"Version\":\"2012-10-17\",\"Statement\":[{\"Effect\":\"Allow\",\"Principal\":{\"AWS\":[\"*\"]},\"Action\":[\"s3:GetBucketLocation\",\"s3:ListBucket\",\"s3:ListBucketMultipartUploads\"],\"Resource\":[\"arn:aws:s3:::" + bucketName + "\"]},{\"Effect\":\"Allow\",\"Principal\":{\"AWS\":[\"*\"]},\"Action\":[\"s3:DeleteObject\",\"s3:GetObject\",\"s3:ListMultipartUploadParts\",\"s3:PutObject\",\"s3:AbortMultipartUpload\"],\"Resource\":[\"arn:aws:s3:::" + bucketName + "/*\"]}]}";minioClient.setBucketPolicy(SetBucketPolicyArgs.builder().bucket(bucketName).config(READ_WRITE).build());}minioClient.putObject(PutObjectArgs.builder().bucket(bucketName).object(fileName).stream(inputStream, multipartFile.getSize(), -1).contentType(multipartFile.getContentType()).build());//路径获取url = minioClient.getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder().bucket(bucketName).object(fileName).method(Method.GET).build());url = url.substring(0, url.indexOf('?'));//常规访问路径获取return url;} catch (Exception e) {throw new IOException(e.getMessage(), e);}}/*** 预览图片** @param fileName* @return*/public String preview(String fileName) {// 查看文件地址GetPresignedObjectUrlArgs build = new GetPresignedObjectUrlArgs().builder().bucket(prop.getBucketName()).object(fileName).method(Method.GET).build();try {String url = minioClient.getPresignedObjectUrl(build);return url;} catch (Exception e) {e.printStackTrace();}return null;}/*** 文件下载** @param fileName 文件名称* @param res      response* @return Boolean*/public void download(String fileName, HttpServletResponse res) {GetObjectArgs objectArgs = GetObjectArgs.builder().bucket(prop.getBucketName()).object(fileName).build();try (GetObjectResponse response = minioClient.getObject(objectArgs)) {byte[] buf = new byte[1024];int len;try (FastByteArrayOutputStream os = new FastByteArrayOutputStream()) {while ((len = response.read(buf)) != -1) {os.write(buf, 0, len);}os.flush();byte[] bytes = os.toByteArray();res.setCharacterEncoding("utf-8");// 设置强制下载不打开// res.setContentType("application/force-download");res.addHeader("Content-Disposition", "attachment;fileName=" + fileName);try (ServletOutputStream stream = res.getOutputStream()) {stream.write(bytes);stream.flush();}}} catch (Exception e) {e.printStackTrace();}}/*** 查看文件对象** @return 存储bucket内文件对象信息*/public List<Item> listObjects() {Iterable<Result<Item>> results = minioClient.listObjects(ListObjectsArgs.builder().bucket(prop.getBucketName()).build());List<Item> items = new ArrayList<>();try {for (Result<Item> result : results) {items.add(result.get());}} catch (Exception e) {e.printStackTrace();return null;}return items;}/*** 删除** @param fileName* @return* @throws Exception*/public boolean remove(String fileName) {try {minioClient.removeObject(RemoveObjectArgs.builder().bucket(prop.getBucketName()).object(fileName).build());} catch (Exception e) {return false;}return true;}/*** 删除文件夹及文件** @param bucketName bucket名称* @param objectName 文件或文件夹名称:以.结尾为文件,以/结尾为文件夹* @since tarzan LIU*/public boolean deleteObjects(String bucketName, String objectName) {if (StringUtils.isNotBlank(objectName)) {if (objectName.endsWith(".") || objectName.endsWith("/")) {Iterable<Result<Item>> list = minioClient.listObjects(ListObjectsArgs.builder().bucket(bucketName).prefix(objectName).recursive(true).build());ExecutorService executorService = Executors.newFixedThreadPool(10);list.forEach(e -> {executorService.execute(new Runnable() {@Overridepublic void run() {try {minioClient.removeObject(RemoveObjectArgs.builder().bucket(bucketName).object(e.get().objectName()).build());} catch (ErrorResponseException ex) {throw new RuntimeException(ex);} catch (InsufficientDataException ex) {throw new RuntimeException(ex);} catch (InternalException ex) {throw new RuntimeException(ex);} catch (InvalidKeyException ex) {throw new RuntimeException(ex);} catch (InvalidResponseException ex) {throw new RuntimeException(ex);} catch (IOException ex) {throw new RuntimeException(ex);} catch (NoSuchAlgorithmException ex) {throw new RuntimeException(ex);} catch (ServerException ex) {throw new RuntimeException(ex);} catch (XmlParserException ex) {throw new RuntimeException(ex);}}});});executorService.shutdown();return true;}}return true;}
}

2.5 测试

1. 业务层

package com.ruoyi.minio.service;import org.springframework.web.multipart.MultipartFile;/*** minio服务*/
public interface MinioService {/*** 文件上传** @param file* @return*/public String upload(MultipartFile file);/*** 文件上传** @param file* @return*/public String uploadFile(String bucketName, String fileName, MultipartFile multipartFile);/*** 预览图片* @param fileName* @return*/public String preview(String fileName);/*** 文件删除** @param fileName* @return*/public boolean remove(String fileName);/*** 删除文件夹及文件** @param bucketName bucket名称* @param objectName 文件或文件夹名称* @since tarzan LIU*/public boolean deleteObjects(String bucketName, String objectName);/*** 删除前几天文件夹* @param bucketName* @param day* @return*/boolean deleteObjectsByDay(String bucketName, int day);
}
package com.ruoyi.minio.service.impl;import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.minio.service.MinioService;
import com.ruoyi.minio.util.MinioUtil;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;import javax.annotation.Resource;
import java.io.IOException;@Service
public class MinioServiceImpl implements MinioService {@Resourceprivate MinioUtil minioUtil;/*** 文件上传** @param file* @return*/@Overridepublic String upload(MultipartFile file) {return minioUtil.upload(file);}/*** 文件上传** @param bucketName* @param fileName* @param multipartFile* @return*/@Overridepublic String uploadFile(String bucketName, String fileName, MultipartFile multipartFile) {try {return minioUtil.uploadFile(bucketName, fileName, multipartFile);} catch (IOException e) {throw new ServiceException("上传失败,请联系管理员");}}/*** 预览图片** @param fileName* @return*/@Overridepublic String preview(String fileName) {return minioUtil.preview(fileName);}/*** 文件删除** @param fileName* @return*/@Overridepublic boolean remove(String fileName) {return minioUtil.remove(fileName);}/*** 删除文件夹及文件** @param bucketName bucket名称* @param objectName 文件或文件夹名称* @since tarzan LIU*/@Overridepublic boolean deleteObjects(String bucketName, String objectName) {return minioUtil.deleteObjects(bucketName, objectName);}/*** 删除前几天文件夹** @param bucketName* @param day* @return*/@Overridepublic boolean deleteObjectsByDay(String bucketName, int day) {String objectName = DateUtils.getDayAgoOrAfterString(day)+"/";return minioUtil.deleteObjects(bucketName, objectName);}
}

2. 控制层

package com.ruoyi.web.controller.minio;import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.minio.service.MinioService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;import javax.annotation.Resource;/*** minio文件管理*/
@RestController
@RequestMapping("/minio")
public class MinioController {@Resourcepublic MinioService minioService;@PostMapping("/upload")public AjaxResult upload(MultipartFile file) {String upload = minioService.upload(file);return AjaxResult.success(upload);}/*** 预览图片** @param fileName* @return*/@GetMapping("/preview")public AjaxResult preview(String fileName) {String preview = minioService.preview(fileName);return AjaxResult.success(preview);}/*** 删除文件** @param fileName* @return*/@GetMapping("/remove")public AjaxResult remove(String fileName) {return AjaxResult.success(minioService.remove(fileName));}/*** 删除文件夹及文件** @param bucketName bucket名称* @param objectName 文件或文件夹名称* @since tarzan LIU*/@GetMapping("/deleteObjects")public AjaxResult deleteObjects(String bucketName, String objectName) {return AjaxResult.success(minioService.deleteObjects(bucketName, objectName));}/*** 删除文件夹及文件** @param bucketName bucket名称* @param objectName 文件或文件夹名称* @since tarzan LIU*/@GetMapping("/deleteObjectsByDay")public AjaxResult deleteObjectsByDay(String bucketName, int day) {return AjaxResult.success(minioService.deleteObjectsByDay(bucketName, day));}
}

相关文章:

SpringBoot整合minio

SpringBoot整合minio 1. 下载及安装1.1 windows版本1.2 Linux版本 2. SpringBoot整合minio2.1 依赖2.2 配置文件2.3 配置类2.4 工具类2.5 测试1. 业务层2. 控制层 1. 下载及安装 1.1 windows版本 目录结构 启动文件 标红的地方按实际安装地更改 echo off REM 声明采用UT…...

3090. 每个字符最多出现两次的最长子字符串

说在前面 &#x1f388;不知道大家对于算法的学习是一个怎样的心态呢&#xff1f;为了面试还是因为兴趣&#xff1f;不管是出于什么原因&#xff0c;算法学习需要持续保持。 题目描述 给你一个字符串 s &#xff0c;请找出满足每个字符最多出现两次的最长子字符串&#xff0c;…...

26.活锁、饥饿锁

两个线程&#xff0c;相互改变了对方结束条件&#xff0c;导致两个线程不能结束。执行时间也都是一样&#xff0c;导致两个线程永远不会结束。 Slf4j public class LiveLockDemo {static volatile int count 10;public static void main(String[] args) {new Thread(() ->…...

docker 安装nginx

一、先查看有没有nginx镜像 docker images 二、发现没有nginx镜像&#xff0c;下载最新镜像 docker pull nginx 三、运行镜像 为了先复制出部分文件&#xff0c;先启动一个临时容器 docker run --name nginx -p 9001:80 -d nginx docker cp nginx:/etc/nginx/conf.d /home/…...

2024年阿里云新用户便宜购买云服务器攻略:5大细节助你降低购买成本

随着互联网的蓬勃发展&#xff0c;无论是个人还是企业&#xff0c;拥有一个稳定且高效的网站或APP已成为提升竞争力的关键。为了将这些项目部署并运行起来&#xff0c;购买一台实用又便宜的云服务器是必不可少的。阿里云作为国内首屈一指的云服务提供商&#xff0c;自然成为了众…...

SSTI模板注入(jinja2)

前面学习了SSTI中的smarty类型&#xff0c;今天学习了Jinja2&#xff0c;两种类型都是flask框架的&#xff0c;但是在注入的语法上还是有不同 SSTI&#xff1a;服务器端模板注入&#xff0c;也属于一种注入类型。与sql注入类似&#xff0c;也是通过凭借进行命令的执行&#xff…...

ESP32学习---ESP-NOW(一)

ESP32学习---ESP-NOW&#xff08;一&#xff09; 官网简介arduino 官网简介 首先看官网的介绍&#xff1a;https://www.espressif.com.cn/zh-hans/solutions/low-power-solutions/esp-now ESP-NOW 是乐鑫定义的一种无线通信协议&#xff0c;能够在无路由器的情况下直接、快速…...

C++核心高级编程 --- 3、函数提高

文章目录 第三章&#xff1a;3.函数提高3.1 函数默认参数3.2 函数占位参数3.3 函数重载3.3.1 函数重载概述3.3.2 注意事项 第三章&#xff1a; 3.函数提高 3.1 函数默认参数 语法结构&#xff1a;返回值类型 函数名 (参数 默认值){} #include <iostream> using name…...

【微服务篇】深入理解分布式消息队列系统

分布式消息队列是一种在多个服务器、应用或服务之间进行消息传递的技术。它使得各个独立的组件可以通过异步消息进行通信&#xff0c;提高了系统的可扩展性、解耦性和可靠性。 典型应用场景 1. 异步处理 在许多系统中&#xff0c;某些任务的处理可能需要较长时间&#xff0c…...

基于k8s的web服务器构建

文章目录 k8s综合项目1、项目规划图2、项目描述3、项目环境4、前期准备4.1、环境准备4.2、ip划分4.3、静态配置ip地址4.4、修改主机名4.5、部署k8s集群4.5.1、关闭防火墙和selinux4.5.2、升级系统4.5.3、每台主机都配置hosts文件&#xff0c;相互之间通过主机名互相访问4.5.4、…...

【名词解释】ImageCaption任务中的CIDEr、n-gram、TF-IDF、BLEU、METEOR、ROUGE 分别是什么?它们是怎样计算的?

CIDEr CIDEr&#xff08;Consensus-based Image Description Evaluation&#xff09;是一种用于自动评估图像描述&#xff08;image captioning&#xff09;任务性能的指标。它主要通过计算生成的描述与一组参考描述之间的相似性来评估图像描述的质量。CIDEr的独特之处在于它考…...

C++其他语法..

1.运算符重载 之前有一个案例如下所示 其中我们可以通过add方法将两个点组成一个新的点 class Point {friend Point add(Point, Point);int m_x;int m_y; public:Point(int x, int y) : m_x(x), m_y(y) {}void display() {cout << "(" << m_x <<…...

【Vue3源码学习】— CH2.6 effect.ts:详解

effect.ts&#xff1a;详解 1. 理解activeEffect1.1 定义1.2 通过一个例子来说明这个过程a. 副作用函数的初始化b. 执行副作用函数前c. 访问state.countd. get拦截器中的track调用e. 修改state.count时的set拦截器f. trigger函数中的依赖重新执行 1.3 实战应用1.4 activeEffect…...

C语言:文件操作(一)

目录 前言 1、为什么使用文件 2、什么是文件 2.1 程序文件 2.2 数据文件 2.3 文件名 3、文件的打开和关闭 3.1 文件指针 3.2 文件的打开和关闭 结&#xff08;一&#xff09; 前言 本篇文章将介绍C语言的文件操作&#xff0c;在后面的内容讲到&#xff1a;为什么使用文…...

集中进行一系列处理——函数

需要多次执行相同的处理&#xff0c;除了编写循环语句之外&#xff0c;还可以集中起来对它进行定义。 对一系列处理进行定义的做法被称为函数&#xff0c;步骤&#xff0c;子程序。 对函数进行定一后&#xff0c;只需要调用该函数就可以了。如果需要对处理的内容进行修正&…...

git diff

1. 如何将库文件的变化生成到patch中 git diff --binary commit1 commit2 > test.patch 打patch&#xff1a; git apply test.patch 2. 如何消除trailing whitespace 问题 git diff --ignore-space-at-eol commit1 commit2 > test.patch 打patch&#xff1a; git ap…...

新手使用GIT上传本地项目到Github(个人笔记)

亲测下面的文章很有用处。 1. 初次使用git上传代码到github远程仓库 - 知乎 (zhihu.com) 2. 使用Git时出现refusing to merge unrelated histories的解决办法 - 知乎...

结合《人力资源管理系统》的Java基础题

1.编写一个Java方法&#xff0c;接受一个整数数组作为参数&#xff0c;返回该数组中工资高于平均工资的员工数量。假设数组中的每个元素都代表一个员工的工资。 2.设计一个Java方法&#xff0c;接受一个字符串数组和一个关键字作为参数&#xff0c;返回包含该关键字的姓名的员…...

PostgreSQL备份还原数据库

1.切换PostgreSQL bin目录 配置Postgresql环境变量后可以不用切换 pg_dump 、psql都在postgresql bin目录下&#xff0c;所以需要切换到bin目录执行命令 2.备份数据库 方式一 语法 pg_dump -h <ip> -U <pg_username> -p <port> -d <databaseName>…...

实现读写分离与优化查询性能:通过物化视图在MySQL、PostgreSQL和SQL Server中的应用

实现读写分离与优化查询性能&#xff1a;通过物化视图在MySQL、PostgreSQL和SQL Server中的应用 在数据库管理中&#xff0c;读写分离是一种常见的性能优化方法&#xff0c;它通过将读操作和写操作分发到不同的服务器或数据库实例上&#xff0c;来减轻单个数据库的负载&#x…...

Neo4j 实战:手把手构建电影知识图谱

1. 为什么选择Neo4j构建电影知识图谱 第一次接触Neo4j时&#xff0c;我就被它处理复杂关系的能力惊艳到了。相比传统的关系型数据库&#xff0c;用图数据库来存储电影数据简直是天作之合。想象一下&#xff0c;当我们需要查询"汤姆汉克斯出演过哪些科幻电影"或者&quo…...

企业级中药实验管理系统管理系统源码|SpringBoot+Vue+MyBatis架构+MySQL数据库【完整版】

&#x1f4a1;实话实说&#xff1a;C有自己的项目库存&#xff0c;不需要找别人拿货再加价。摘要 随着中医药产业的快速发展&#xff0c;中药实验数据的规模化和复杂化对信息化管理提出了更高要求。传统的中药实验管理多依赖手工记录和纸质档案&#xff0c;存在数据易丢失、查询…...

为什么顶尖AI产品团队正秘密重构设计系统?——AI原生用户体验的4层认知断层与SITS 2026破局公式

更多请点击&#xff1a; https://intelliparadigm.com 第一章&#xff1a;AI原生用户体验设计&#xff1a;SITS 2026交互设计新趋势 AI原生体验不再将模型能力“封装后隐藏”&#xff0c;而是让智能成为界面的第一公民——用户在输入框中键入自然语言时&#xff0c;系统实时推…...

从Prompt Gateway到Content SLA引擎:2026奇点大会上最受瞩目的5个开源组件,已集成至CNCF沙箱(限前500名开发者获取部署手册)

更多请点击&#xff1a; https://intelliparadigm.com 第一章&#xff1a;AI原生内容生成平台&#xff1a;2026奇点智能技术大会AIGC系统搭建 在2026奇点智能技术大会上&#xff0c;主办方构建了一套面向多模态协同创作的AI原生内容生成平台&#xff08;AIGC-OS&#xff09;&a…...

3分钟快速解锁碧蓝航线全皮肤:Perseus游戏补丁终极指南

3分钟快速解锁碧蓝航线全皮肤&#xff1a;Perseus游戏补丁终极指南 【免费下载链接】Perseus Azur Lane scripts patcher. 项目地址: https://gitcode.com/gh_mirrors/pers/Perseus 还在为碧蓝航线中那些精美皮肤无法体验而烦恼吗&#xff1f;Perseus原生库补丁为你提供…...

打破语言壁垒:Translumo屏幕实时翻译工具的终极使用指南

打破语言壁垒&#xff1a;Translumo屏幕实时翻译工具的终极使用指南 【免费下载链接】Translumo Advanced real-time screen translator for games, hardcoded subtitles in videos, static text and etc. 项目地址: https://gitcode.com/gh_mirrors/tr/Translumo 你是否…...

代码与图形的双向桥梁:在Draw.io中实现Mermaid图表工作流

代码与图形的双向桥梁&#xff1a;在Draw.io中实现Mermaid图表工作流 【免费下载链接】drawio_mermaid_plugin Mermaid plugin for drawio desktop 项目地址: https://gitcode.com/gh_mirrors/dr/drawio_mermaid_plugin 在技术文档和系统设计的日常工作中&#xff0c;开…...

Transformer架构优化实战2026:注意力机制、KV Cache与推理加速完整指南

Transformer架构诞生已近十年&#xff0c;但它的工程优化故事才刚刚开始。2026年&#xff0c;理解并掌握Transformer的核心优化技术&#xff0c;是每个LLM工程师的必修课。一、为什么Transformer的优化如此重要一个7B参数的LLM在A100上推理时&#xff0c;如果没有优化&#xff…...

SpringBoot + Tomcat部署,你的文件上传接口有‘定时炸弹’吗?聊聊/tmp目录清理那点事

SpringBoot文件上传的临时目录陷阱&#xff1a;从原理到防御性部署策略 当你在凌晨三点被报警短信惊醒&#xff0c;发现生产环境文件上传功能突然失效时&#xff0c;那种绝望感只有经历过的人才能体会。这不是什么复杂的业务逻辑错误&#xff0c;而是一个看似微不足道的临时目录…...

LinkSwift:九大网盘直链下载终极解决方案,三步告别限速困扰

LinkSwift&#xff1a;九大网盘直链下载终极解决方案&#xff0c;三步告别限速困扰 【免费下载链接】Online-disk-direct-link-download-assistant 一个基于 JavaScript 的网盘文件下载地址获取工具。基于【网盘直链下载助手】修改 &#xff0c;支持 百度网盘 / 阿里云盘 / 中国…...