Spring Boot輕松整合Minio實現文件上傳下載功能

一、Linux 安裝Minio

安裝

/root/xxkfz/soft目錄下面創建文件minio文件夾,進入minio文件夾,并創建data目錄;

[root@xxkfz?soft]#?mkdir?minio
[root@xxkfz?soft]#?cd?minio
[root@xxkfz?minio]#?mkdir?data

執行如下命令進行下載

[root@xxkfz?minio]#?wget?https://dl.min.io/server/minio/release/linux-amd64/minio
[root@xxkfz?minio]#?chmod?+x?minio??#?賦權

下載完成后如下所示:

設置賬號密碼

minio 默認賬號密碼為?minioadmin/minioadmin

[root@xxkfz?minio]#?export?MINIO_ACCESS_KEY=admin?#?設置控制臺賬號(最少3位)
[root@xxkfz?minio]#?export?MINIO_SECRET_KEY=12345678?#?設置密碼(最少8位)

直接設置管理員賬號密碼?編輯?/etc/profile?文件即可

[root@xxkfz?minio]#?vim?/etc/profile

編輯/etc/profile文件,追加如下內容:

#===============================Minio=============================================
#?set?minio?environment
export?MINIO_ROOT_USER=admin
export?MINIO_ROOT_PASSWORD=admin123

可省略?設置賬號密碼?此步驟!12

啟動

進入執行文件目錄/root/xxkfz/soft/minio,自定義端口啟動(默認端口:9000)

[root@xxkfz?minio]#?nohup?/root/xxkfz/soft/minio/minio?server?--address?:9001?--console-address?:9002?/root/xxkfz/soft/minio/data?>/root/xxkfz/soft/minio/minio.log?2>&1?&

說明:

?nohup?為后臺啟動?./minio server?啟動命令?--address :9001?指定API端口?--console-address :9002?指定控制臺端口?/usr/local/minio/data?指定存儲目錄?>/usr/local/minio/minio.log 2>&1?控制臺日志重定向到/usr/local/minio/minio.log文件中?&?后臺運行

啟動成功:

啟動成功

啟動成功

啟動成功

注意:瀏覽器訪問需要開啟防火墻端口!

阿里云配置開放9001、9002端口

測試訪問:http://IP地址:9002

輸入賬號密碼:?admin/12345678?登錄成功!

設置開機自啟動

設置Minio服務器宕機后自動重啟

進入init.d目錄

[root@xxkfz?minio]#?cd?/etc/rc.d/init.d

新建minio.sh shell腳本文件

[root@xxkfz?init.d]#?vim?minio.sh?

shell腳本內容

#!/bin/bash
#chkconfig:?2345?10?90
#description:?ping10
nohup?/root/xxkfz/soft/minio/minio?server?--address?:9001?--console-address?:9002?/root/xxkfz/soft/minio/data?>/root/xxkfz/soft/minio/minio.log?2>&1?&

給shell腳本賦權

chmod?+x?minio.sh

添加到開機自啟動服務中

chkconfig?--add?minio.sh

設置開機自啟動

chkconfig?minio.sh?on

查看是否添加成功

chkconfig?--list

二、Spring Boot整合Minio

項目搭建

項目基本結構

項目基本結構

項目基本結構

引入依賴

pom.xml

???<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><dependency><groupId>io.minio</groupId><artifactId>minio</artifactId><version>8.2.2</version></dependency><dependency><groupId>org.apache.commons</groupId><artifactId>commons-lang3</artifactId><version>3.11</version></dependency>

配置MinIo

application.yml

minio:endpoint:?http://IP地址:9001accessKey:?adminsecretKey:?12345678bucketName:?xk-admin#?配置端口號
server:port:?8099

編寫配置類

MinioConfig.java

/***?@program:?xxkfz-minio*?@ClassName?MinioConfig.java*?@author:?公眾號:小小開發者*?@create:?2024-03-13?10:53*?@description:?Minio?配置類**/
@Data
@Configuration
public?class?MinioConfig?{/***?訪問地址*/@Value("${minio.endpoint}")private?String?endpoint;/***?accessKey類似于用戶ID,用于唯一標識你的賬戶*/@Value("${minio.accessKey}")private?String?accessKey;/***?secretKey是你賬戶的密碼*/@Value("${minio.secretKey}")private?String?secretKey;/***?默認存儲桶*/@Value("${minio.bucketName}")private?String?bucketName;@Beanpublic?MinioClient?minioClient()?{MinioClient?minioClient?=?MinioClient.builder().endpoint(endpoint).credentials(accessKey,?secretKey).build();return?minioClient;}
}

編寫Minio操作工具類

MinioUtils.java

/***?@program:?xxkfz-minio*?@ClassName?MinioUtils.java*?@author:?公眾號:小小開發者*?@create:?2024-03-13?10:55*?@description:?MinIO操作工具類**/
@Slf4j
@Component
public?class?MinioUtils?{@Autowiredprivate?MinioClient?minioClient;/***?啟動SpringBoot容器的時候初始化Bucket*?如果沒有Bucket則創建**?@param?bucketName*/public?void?createBucket(String?bucketName)?{try?{if?(!bucketExists(bucketName))?{minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());log.info("創建bucketName?=?{}完成!",?bucketName);return;}log.info("bucketName?=?{}已存在!策略為:{}",?bucketName,?getBucketPolicy(bucketName));}?catch?(Exception?e)?{log.error("創建bucketName?=?{}異常!e?=?{}",?bucketName,?e);}}/***?判斷Bucket是否存在,true:存在,false:不存在**?@param?bucketName*?@return*/@SneakyThrowspublic?boolean?bucketExists(String?bucketName)?{return?minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());}/***?獲得Bucket的策略**?@param?bucketName*?@return*/@SneakyThrowspublic?String?getBucketPolicy(String?bucketName)?{return?minioClient.getBucketPolicy(GetBucketPolicyArgs.builder().bucket(bucketName).build());}/***?獲得所有Bucket列表**?@return*/@SneakyThrowspublic?List<Bucket>?getAllBuckets()?{return?minioClient.listBuckets();}/***?根據bucketName獲取其相關信息**?@param?bucketName*?@return*/@SneakyThrows(Exception.class)public?Optional<Bucket>?getBucket(String?bucketName)?{return?getAllBuckets().stream().filter(b?->?b.name().equals(bucketName)).findFirst();}/***?根據bucketName刪除Bucket,true:刪除成功;?false:刪除失敗,文件或已不存在**?@param?bucketName*?@throws?Exception*/@SneakyThrows(Exception.class)public?void?removeBucket(String?bucketName)?{minioClient.removeBucket(RemoveBucketArgs.builder().bucket(bucketName).build());}/***?判斷文件是否存在**?@param?bucketName*?@param?objectName*?@return*/public?boolean?isObjectExist(String?bucketName,?String?objectName)?{boolean?exist?=?true;try?{minioClient.statObject(StatObjectArgs.builder().bucket(bucketName).object(objectName).build());}?catch?(Exception?e)?{log.error("[Minio工具類]>>>>?判斷文件是否存在,?異常:",?e);exist?=?false;}return?exist;}/***?判斷文件夾是否存在**?@param?bucketName*?@param?objectName*?@return*/public?boolean?isFolderExist(String?bucketName,?String?objectName)?{boolean?exist?=?false;try?{Iterable<Result<Item>>?results?=?minioClient.listObjects(ListObjectsArgs.builder().bucket(bucketName).prefix(objectName).recursive(false).build());for?(Result<Item>?result?:?results)?{Item?item?=?result.get();if?(item.isDir()?&&?objectName.equals(item.objectName()))?{exist?=?true;}}}?catch?(Exception?e)?{log.error("[Minio工具類]>>>>?判斷文件夾是否存在,異常:",?e);exist?=?false;}return?exist;}/***?根據文件前置查詢文件**?@param?bucketName?存儲桶*?@param?prefix?????前綴*?@param?recursive??是否使用遞歸查詢*?@return?MinioItem?列表*/@SneakyThrows(Exception.class)public?List<Item>?getAllObjectsByPrefix(String?bucketName,?String?prefix,?boolean?recursive)?{List<Item>?list?=?new?ArrayList<>();Iterable<Result<Item>>?objectsIterator?=?minioClient.listObjects(ListObjectsArgs.builder().bucket(bucketName).prefix(prefix).recursive(recursive).build());if?(objectsIterator?!=?null)?{for?(Result<Item>?o?:?objectsIterator)?{Item?item?=?o.get();list.add(item);}}return?list;}/***?獲取文件流**?@param?bucketName?存儲桶*?@param?objectName?文件名*?@return?二進制流*/@SneakyThrows(Exception.class)public?InputStream?getObject(String?bucketName,?String?objectName)?{return?minioClient.getObject(GetObjectArgs.builder().bucket(bucketName).object(objectName).build());}/***?斷點下載**?@param?bucketName?存儲桶*?@param?objectName?文件名稱*?@param?offset?????起始字節的位置*?@param?length?????要讀取的長度*?@return?二進制流*/@SneakyThrows(Exception.class)public?InputStream?getObject(String?bucketName,?String?objectName,?long?offset,?long?length)?{return?minioClient.getObject(GetObjectArgs.builder().bucket(bucketName).object(objectName).offset(offset).length(length).build());}/***?獲取路徑下文件列表**?@param?bucketName?存儲桶*?@param?prefix?????文件名稱*?@param?recursive??是否遞歸查找,false:模擬文件夾結構查找*?@return?二進制流*/public?Iterable<Result<Item>>?listObjects(String?bucketName,?String?prefix,?boolean?recursive)?{return?minioClient.listObjects(ListObjectsArgs.builder().bucket(bucketName).prefix(prefix).recursive(recursive).build());}/***?使用MultipartFile進行文件上傳**?@param?bucketName??存儲桶*?@param?file????????文件名*?@param?objectName??對象名*?@param?contentType?類型*?@return*/@SneakyThrows(Exception.class)public?ObjectWriteResponse?uploadFile(String?bucketName,?MultipartFile?file,?String?objectName,?String?contentType)?{InputStream?inputStream?=?file.getInputStream();return?minioClient.putObject(PutObjectArgs.builder().bucket(bucketName).object(objectName).contentType(contentType).stream(inputStream,?inputStream.available(),?-1).build());}/***?圖片上傳**?@param?bucketName*?@param?imageBase64*?@param?imageName*?@return*/public?ObjectWriteResponse?uploadImage(String?bucketName,?String?imageBase64,?String?imageName)?{if?(!StringUtils.isEmpty(imageBase64))?{InputStream?in?=?base64ToInputStream(imageBase64);String?newName?=?System.currentTimeMillis()?+?"_"?+?imageName?+?".jpg";String?year?=?String.valueOf(new?Date().getYear());String?month?=?String.valueOf(new?Date().getMonth());return?uploadFile(bucketName,?year?+?"/"?+?month?+?"/"?+?newName,?in);}return?null;}public?static?InputStream?base64ToInputStream(String?base64)?{ByteArrayInputStream?stream?=?null;try?{byte[]?bytes?=?Base64.getEncoder().encode(base64.trim().getBytes());stream?=?new?ByteArrayInputStream(bytes);}?catch?(Exception?e)?{e.printStackTrace();}return?stream;}/***?上傳本地文件**?@param?bucketName?存儲桶*?@param?objectName?對象名稱*?@param?fileName???本地文件路徑*?@return*/@SneakyThrows(Exception.class)public?ObjectWriteResponse?uploadFile(String?bucketName,?String?objectName,?String?fileName)?{return?minioClient.uploadObject(UploadObjectArgs.builder().bucket(bucketName).object(objectName).filename(fileName).build());}/***?通過流上傳文件**?@param?bucketName??存儲桶*?@param?objectName??文件對象*?@param?inputStream?文件流*?@return*/@SneakyThrows(Exception.class)public?ObjectWriteResponse?uploadFile(String?bucketName,?String?objectName,?InputStream?inputStream)?{return?minioClient.putObject(PutObjectArgs.builder().bucket(bucketName).object(objectName).stream(inputStream,?inputStream.available(),?-1).build());}/***?創建文件夾或目錄**?@param?bucketName?存儲桶*?@param?objectName?目錄路徑*?@return*/@SneakyThrows(Exception.class)public?ObjectWriteResponse?createDir(String?bucketName,?String?objectName)?{return?minioClient.putObject(PutObjectArgs.builder().bucket(bucketName).object(objectName).stream(new?ByteArrayInputStream(new?byte[]{}),?0,?-1).build());}/***?獲取文件信息,?如果拋出異常則說明文件不存在**?@param?bucketName?存儲桶*?@param?objectName?文件名稱*?@return*/@SneakyThrows(Exception.class)public?String?getFileStatusInfo(String?bucketName,?String?objectName)?{return?minioClient.statObject(StatObjectArgs.builder().bucket(bucketName).object(objectName).build()).toString();}/***?拷貝文件**?@param?bucketName????存儲桶*?@param?objectName????文件名*?@param?srcBucketName?目標存儲桶*?@param?srcObjectName?目標文件名*/@SneakyThrows(Exception.class)public?ObjectWriteResponse?copyFile(String?bucketName,?String?objectName,?String?srcBucketName,?String?srcObjectName)?{return?minioClient.copyObject(CopyObjectArgs.builder().source(CopySource.builder().bucket(bucketName).object(objectName).build()).bucket(srcBucketName).object(srcObjectName).build());}/***?刪除文件**?@param?bucketName?存儲桶*?@param?objectName?文件名稱*/@SneakyThrows(Exception.class)public?void?removeFile(String?bucketName,?String?objectName)?{minioClient.removeObject(RemoveObjectArgs.builder().bucket(bucketName).object(objectName).build());}/***?批量刪除文件**?@param?bucketName?存儲桶*?@param?keys???????需要刪除的文件列表*?@return*/public?void?removeFiles(String?bucketName,?List<String>?keys)?{List<DeleteObject>?objects?=?new?LinkedList<>();keys.forEach(s?->?{objects.add(new?DeleteObject(s));try?{removeFile(bucketName,?s);}?catch?(Exception?e)?{log.error("[Minio工具類]>>>>?批量刪除文件,異常:",?e);}});}/***?獲取文件外鏈**?@param?bucketName?存儲桶*?@param?objectName?文件名*?@param?expires????過期時間?<=7?秒?(外鏈有效時間(單位:秒))*?@return?url*/@SneakyThrows(Exception.class)public?String?getPresignedObjectUrl(String?bucketName,?String?objectName,?Integer?expires)?{GetPresignedObjectUrlArgs?args?=?GetPresignedObjectUrlArgs.builder().expiry(expires).bucket(bucketName).object(objectName).build();return?minioClient.getPresignedObjectUrl(args);}/***?獲得文件外鏈**?@param?bucketName*?@param?objectName*?@return?url*/@SneakyThrows(Exception.class)public?String?getPresignedObjectUrl(String?bucketName,?String?objectName)?{GetPresignedObjectUrlArgs?args?=?GetPresignedObjectUrlArgs.builder().bucket(bucketName).object(objectName).method(Method.GET).build();return?minioClient.getPresignedObjectUrl(args);}/***?將URLDecoder編碼轉成UTF8**?@param?str*?@return*?@throws?UnsupportedEncodingException*/public?String?getUtf8ByURLDecoder(String?str)?throws?UnsupportedEncodingException?{String?url?=?str.replaceAll("%(?![0-9a-fA-F]{2})",?"%25");return?URLDecoder.decode(url,?"UTF-8");}
}

項目啟動初始化配置

創建配置類InitConfig.java,并實現了InitializingBean接口重寫afterPropertiesSet方法。

該方法主要實現邏輯:在項目啟動的時候初始化Bucket,如果沒有則進行創建!

InitConfig.java

/***?@program:?xxkfz-minio*?@ClassName?Init.java*?@author:?wust*?@create:?2024-03-16?10:34*?@description:?項目啟動初始化配置**/
@Component
@Slf4jpublic?class?InitConfig?implements?InitializingBean?{@Autowiredprivate?MinioUtils?minioUtils;@Autowiredprivate?MinioConfig?minioConfig;@Overridepublic?void?afterPropertiesSet()?throws?Exception?{//?項目啟動創建Bucket,不存在則進行創建minioUtils.createBucket(minioConfig.getBucketName());}
}

編寫測試接口

MinioController.java

/***?@program:?xxkfz-minio*?@ClassName?OSSController.java*?@author:?wust*?@create:?2024-03-13?11:01*?@description:**/
@Slf4j
@RestController
@RequestMapping("/oss")
public?class?MinioController?{@Autowiredprivate?MinioUtils?minioUtils;@Autowiredprivate?MinioConfig?minioConfig;/***?文件上傳**?@param?file*/@PostMapping("/upload")public?String?upload(@RequestParam("file")?MultipartFile?file)?{try?{//文件名String?fileName?=?file.getOriginalFilename();String?newFileName?=?System.currentTimeMillis()?+?"."?+?StringUtils.substringAfterLast(fileName,?".");//類型String?contentType?=?file.getContentType();minioUtils.uploadFile(minioConfig.getBucketName(),?file,?newFileName,?contentType);return?"上傳成功,文件名:"?+?newFileName;}?catch?(Exception?e)?{e.printStackTrace();return?"上傳失敗";}}/***?刪除**?@param?fileName*/@DeleteMapping("/")public?void?delete(@RequestParam("fileName")?String?fileName)?{minioUtils.removeFile(minioConfig.getBucketName(),?fileName);}/***?獲取文件信息**?@param?fileName*?@return*/@GetMapping("/info")public?String?getFileStatusInfo(@RequestParam("fileName")?String?fileName)?{return?minioUtils.getFileStatusInfo(minioConfig.getBucketName(),?fileName);}/***?獲取文件外鏈**?@param?fileName*?@return*/@GetMapping("/url")public?String?getPresignedObjectUrl(@RequestParam("fileName")?String?fileName)?{return?minioUtils.getPresignedObjectUrl(minioConfig.getBucketName(),?fileName);}/***?文件下載**?@param?fileName*?@param?response*/@GetMapping("/download")public?void?download(@RequestParam("fileName")?String?fileName,?HttpServletResponse?response)?{try?{InputStream?fileInputStream?=?minioUtils.getObject(minioConfig.getBucketName(),?fileName);response.setHeader("Content-Disposition",?"attachment;filename="?+?fileName);response.setContentType("application/force-download");response.setCharacterEncoding("UTF-8");IOUtils.copy(fileInputStream,?response.getOutputStream());}?catch?(Exception?e)?{log.error("下載失敗");}}
}

測試驗證

啟動項目:

上傳圖片

測試接口:http://localhost:8099/oss/upload

進入服務器查看文件上傳情況。

進入目錄:/root/xxkfz/soft/minio/data/xk-admin

當然,也可以直接訪問minio的地址:http://IP地址:9001/xk-admin/1710558001536.jpg。驗證文件是否上傳成功。

獲取文件信息

測試接口:http://localhost:8099/oss/info

獲取文件外鏈

測試接口:http://localhost:8099/oss/url

下載文件

測試接口:http://localhost:8099/oss/download

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/43452.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/43452.shtml
英文地址,請注明出處:http://en.pswp.cn/web/43452.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Java內存劃分詳解:從基礎到進階

Java內存劃分詳解&#xff1a;從基礎到進階 1. 程序計數器&#xff08;Program Counter Register&#xff09;2. Java虛擬機棧&#xff08;Java Virtual Machine Stack&#xff09;3. 堆&#xff08;Heap&#xff09;4. 方法區&#xff08;Method Area&#xff09;5. 運行時常量…

DDD架構面試問題

基礎概念 什么是領域驅動設計&#xff08;DDD&#xff09;&#xff1f; 請解釋一下DDD的核心思想和目標。 DDD中的領域&#xff08;Domain&#xff09;是什么&#xff1f; 請描述一下領域的概念以及它在軟件開發中的重要性。 什么是限界上下文&#xff08;Bounded Context&am…

ArduPilot開源代碼之OpticalFlow_backend

ArduPilot開源代碼之OpticalFlow_backend 1. 源由2. Library設計3. 重要例程3.1 OpticalFlow_backend::_update_frontend3.2 OpticalFlow_backend::_applyYaw 4. 總結5. 參考資料 1. 源由 光流計是一種低成本定位傳感器&#xff0c;所有的光流計設備傳感驅動代碼抽象公共部分統…

[計網初識1] TCP/UDP

學習內容 1.TCP建立鏈接的3次握手&#xff0c;斷開連接的4次揮手 2.TCP報文段組成 內容 1.TCP 建立連接的3次握手? 假設主動方是客戶端&#xff0c;被動方是服務端。 第一次 客戶端給服務端發送 “hello,我是客戶端” (TCP段中 SYN1) 第二次 服務端給客戶端發送"我接…

從零開始的python學習生活2

接上封裝 class Phone:__volt0.5def __keepsinglecore(self):print("讓cpu以單核運行")def if5G(self):if self.__volt>1:print("5G通話已開啟")else:self.__keepsinglecore()print("電量不足&#xff0c;無法使用5G通話&#xff0c;已經設置為單…

Django項目創建的準備工作【 2 】

【 一 】調整后端目錄 #1 目錄結構 """ ├── luffy_api├── logs/ # 項目運行時/開發時日志目錄 - 包├── manage.py # 腳本文件├── luffy_api/ # 項目主應用&#xff0c;開發時的代碼保存 - 包├── apps/ …

【Git基本操作】添加文件 | 修改文件 | 及其各場景下.git目錄樹的變化

目錄 1. 添加文件&add操作和commit操作 2. .git樹狀目錄的變化 3. git其他操作 4. 修改文件 4.1 git status 4.2 git diff 1. 添加文件&add操作和commit操作 add操作&#xff1a;將工作區中所有文件的修改內容 添加進版本庫的暫存區中。commit操作&#xff1a;…

云端編碼:將您的技術API文檔安全存儲在iCloud的最佳實踐

云端編碼&#xff1a;將您的技術API文檔安全存儲在iCloud的最佳實踐 作為一名技術專業人士&#xff0c;管理不斷增長的API文檔庫是一項挑戰。iCloud提供了一個無縫的解決方案&#xff0c;允許您在所有設備上存儲、同步和訪問您的個人技術API文檔。本文將指導您如何在iCloud中高…

系統服務綜合實驗(dns服務,nfs服務)

題目&#xff1a;現有主機 node01 和 node02&#xff0c;完成如下需求&#xff1a; 1、在 node01 主機上提供 DNS 和 WEB 服務 2、dns 服務提供本實驗所有主機名解析 3、web服務提供 www.rhce.com 虛擬主機 4…

three-tile: 1. 第一個three-tile程序

上篇介紹了&#xff1a;three-tile&#xff1a; 一個開源的輕量級三維瓦片庫-CSDN博客 three-tile 是一個開源的輕量級三維瓦片庫&#xff0c;它基于threejs使用typescript開發&#xff0c;提供一個三維地形模型&#xff0c;能輕松給你的應用增加三維瓦片地圖。 項目地址&…

C#知識|賬號管理系統:UI層-添加賬號窗體設計思路及流程。

哈嘍,你好啊,我是雷工! 前邊練習過詳情頁窗體的設計思路及流程: 《C#知識|上位機UI設計-詳情窗體設計思路及流程(實例)》 本節練習添加賬號窗體的UI設計,以下為學習筆記。 01 效果展示 02 添加窗體 在UI層添加Windows窗體,設置名稱為:FrmAddAcount.cs 設置窗體屬…

Nginx七層(應用層)反向代理:UWSGI代理uwsgi_pass篇

Nginx七層&#xff08;應用層&#xff09;反向代理 UWSGI代理uwsgi_pass篇 - 文章信息 - Author: 李俊才 (jcLee95) Visit me at CSDN: https://jclee95.blog.csdn.netMy WebSite&#xff1a;http://thispage.tech/Email: 291148484163.com. Shenzhen ChinaAddress of this a…

數據結構模板2

Trie樹&#xff1a;用來高效存儲和查找字符串集合的數據結構&#xff1a; 模板題&#xff1a;https://www.acwing.com/problem/content/837/ AC代碼&#xff1a; #include<bits/stdc.h> using namespace std; int son[100010][26],cnt[100010],idx; char str[100010]; …

數據的洞察力:SQL Server Analysis Services在數據分析中的卓越應用

數據的洞察力&#xff1a;SQL Server Analysis Services在數據分析中的卓越應用 在商業智能和數據分析領域&#xff0c;SQL Server Analysis Services (SSAS) 是一款強大的工具&#xff0c;它提供了多維數據和數據挖掘模型的創建、部署和管理功能。本文將深入探討如何在SQL Se…

云端生活,智能管理:在iCloud中打造您的個人購物清單與預算計劃

云端生活&#xff0c;智能管理&#xff1a;在iCloud中打造您的個人購物清單與預算計劃 在快節奏的現代生活中&#xff0c;個人財務管理和購物規劃變得尤為重要。iCloud提供了一個強大的平臺&#xff0c;讓我們能夠存儲、同步和共享個人購物清單與預算計劃。本文將詳細介紹如何…

代碼隨想錄算法訓練營第二十九天

452. 用最少數量的箭引爆氣球 這道題目我原本的想法是只要當前的氣球半徑范圍在已有的箭頭能夠擊穿的氣球半徑內就可以實現 但是 箭射出去的地方是一個值 而不是一個范圍 因此有相同的重疊范圍的許多氣球并一定都有相同的值&#xff0c;因此這種方法不可取 這題的主要局部最…

最短路徑算法(算法篇)

算法之最短路徑算法 最短路徑算法 概念&#xff1a; 考查最短路徑問題&#xff0c;可能會輸入一個賦權圖(也就是邊帶有權的圖)&#xff0c;則一條路徑的v1v2…vN的值就是對路徑的邊的權求和&#xff0c;這叫做賦權路徑長&#xff0c;如果是無權路徑長就是單純的路徑上的邊數。…

mac安裝配置cmake

本機是2015 macbook pro mid&#xff0c;已經有點老了&#xff0c;用homebrew下cmake老出問題 其實cmake官網安裝也不麻煩 一、官網下載對應安裝包 Download CMake 和所有dmg文件一樣安裝 二、改成命令行使用 一般來說 tutorial 給的都是命令行build 命令行的設置如下&am…

手機下載APP (uniapp/vue)

一、uniapp <template><view class"content"><view class"appName">{{ formData.appName }}</view><view class"appInfo">{{ formData.appInfo }}</view><image class"logo" :src"formDa…

批量修改Git歷史commit信息中的username

之前很長一段時間GitHub上的提交都在使用工作賬戶, 導致私人倉庫中的提交者比較混亂. 在StackOver里面找到了一個bash腳本可以批量修改username, 在這里記錄一下. 修改的步驟一共兩步: 執行修改腳本將本地修改同步到Git服務器 首先我們來看腳本: #!/bin/shgit filter-branch…