一、MinIO的下載安裝以及基本使用
1.下載地址:https://dl.min.io/server/minio/release/windows-amd64/minio.exe
2.下載好後需要手動建立【data】資料夾用於儲存Minio中的資料
3.在對應檔案路徑處,鍵入【cmd】 後設定MinIO的一些變數(第一次啟動需要配置)
set MINIO_ROOT_USER=admin set MINIO_ROOT_PASSWORD=admin123 set MINIO_ACCESS_KEY=admin set MINIO_SECRET_KEY=admin123
5.下面是我踩的坑,如果只設定了MINIO_ROOT_USER和MINIO_ROOT_PASSWORD的值,而不設定MINIO_ACCESS_KEY和MINIO_SECRET_KEY的值,當啟動minio服務的時候就會報以下異常:
6. 啟動minio服務
minio.exe server data
7.進入登入頁面後,輸入對應的使用者名稱和密碼,也就是之前設定的MINIO_ROOT_USER和MINIO_ROOT_PASSWORD的值。
8. 進入主介面後,點選左側導航欄中的Buckets,然後點選Create Bucket。
9.進入該桶,點選upload,上傳一個檔案
10.點選左側導航欄中的Buckets,進入該桶,修改許可權為public,這樣外界就可以訪問上傳的檔案了。
桶的預設許可權是private,所以外界訪問不到,需要修改訪問許可權為public,但是要注意安全問題
二. SpringBoot整合MinIO
1.引入依賴
<dependency> <groupId>io.minio</groupId> <artifactId>minio</artifactId> <version>7.0.2</version> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.20</version> </dependency>
2.編寫配置檔案
server:
port: 8080
spring:
# 配置檔案上傳大小限制
servlet:
multipart:
max-file-size: 200MB
max-request-size: 200MB
minio:
host: http://127.0.0.1:9000 # 訪問地址
url: ${minio.host}/${minio.bucket}/ # 物件儲存服務的url
access-key: minioadmin # 登入賬號
secret-key: minioadmin # 登入賬號密碼
bucketName: test-bucket # 檔案桶的名稱
bucket: public // 許可權
3.編寫minio配置類
@Configuration public class MinIoClientConfig { /** * minio配置 */ @Value("${minio.url}") private String endpoint; @Value("${minio.accessKey}") private String accessKey; @Value("${minio.secretKey}") private String secretKey; @Value("${minio.bucketName}") private String bucketName; /** * 注入minio客戶端 * * @return minio客戶端物件 */ @Bean public MinioClient minioClient() { return MinioClient.builder().endpoint(endpoint).credentials(accessKey, secretKey).build(); } }
4.編寫minio工具類
@Component public class MinioUtil { /** * minio配置 */ @Value("${minio.url}") private String endpoint; @Autowired private MinioClient minioClient; /** * 建立一個桶 */ public void createBucket(String bucket) throws Exception { boolean found = minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucket).build()); if (!found) { minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucket).build()); } } /** * 上傳一個檔案 */ public void uploadFile(InputStream stream, String bucket, String objectName) throws Exception { ObjectWriteResponse objectWriteResponse = minioClient.putObject(PutObjectArgs.builder().bucket(bucket).object(objectName) .stream(stream, -1, 10485760).build()); System.out.println(objectWriteResponse.object() + " is uploaded successfully."); } /** * 列出所有的桶 */ public List<String> listBuckets() throws Exception { List<Bucket> list = minioClient.listBuckets(); List<String> names = new ArrayList<>(); list.forEach(b -> { names.add(b.name()); }); return names; } /** * 列出一個桶中的所有檔案和目錄 */ public List<Fileinfo> listFiles(String bucket) throws Exception { Iterable<Result<Item>> results = minioClient.listObjects( ListObjectsArgs.builder().bucket(bucket).recursive(true).build()); List<Fileinfo> infos = new ArrayList<>(); results.forEach(r->{ Fileinfo info = new Fileinfo(); try { Item item = r.get(); info.setFilename(item.objectName()); info.setDirectory(item.isDir()); info.setFilepath(endpoint+"/"+bucket+"/"+item.objectName()); infos.add(info); } catch (Exception e) { e.printStackTrace(); } }); return infos; } /** * 下載一個檔案 */ public InputStream download(String bucket, String objectName) throws Exception { InputStream stream = minioClient.getObject( GetObjectArgs.builder().bucket(bucket).object(objectName).build()); return stream; } /** * 刪除一個桶 */ public void deleteBucket(String bucket) throws Exception { minioClient.removeBucket(RemoveBucketArgs.builder().bucket(bucket).build()); } /** * 刪除一個物件 */ public void deleteObject(String bucket, String objectName) throws Exception { minioClient.removeObject(RemoveObjectArgs.builder().bucket(bucket).object(objectName).build()); } /** * 複製檔案 */ public void copyObject(String sourceBucket, String sourceObject, String targetBucket, String targetObject) throws Exception { this.createBucket(targetBucket); minioClient.copyObject(CopyObjectArgs.builder().bucket(targetBucket).object(targetObject) .source(CopySource.builder().bucket(sourceBucket).object(sourceObject).build()).build()); } /** * 獲取檔案資訊 */ public String getObjectInfo(String bucket, String objectName) throws Exception { return minioClient.statObject(StatObjectArgs.builder().bucket(bucket).object(objectName).build()).toString(); } /** * 生成一個給HTTP GET請求用的presigned URL。 * 瀏覽器/移動端的客戶端可以用這個URL進行下載, * 即使其所在的儲存桶是私有的。 */ public String getPresignedObjectUrl(String bucketName, String objectName, Integer expires) throws Exception { GetPresignedObjectUrlArgs build = GetPresignedObjectUrlArgs .builder().bucket(bucketName).object(objectName).expiry(expires).method(Method.GET).build(); return minioClient.getPresignedObjectUrl(build); } /** * 獲取minio中所有的檔案 */ public List<Fileinfo> listAllFile() throws Exception { List<String> list = this.listBuckets(); List<Fileinfo> fileinfos = new ArrayList<>(); for (String bucketName : list) { fileinfos.addAll(this.listFiles(bucketName)); } return fileinfos; } }
5.編寫檔案實體類
@Data public class Fileinfo { String filename; String filepath; Boolean directory; }
6.編寫介面響應實體
@Data public class ResultData<T> { public static final Integer SUCCESS_CODE = 200; public static final Integer FAIL_CODE = 4000; public static final String SUCCESS_MESSAGE = "操作成功"; public static final String FAIL_MESSAGE = "操作失敗"; /** * 返回狀態碼 */ private Integer code; /** * 返回資訊 */ private String message; /** * 返回資料 */ private T data; public ResultData() { } public static <T> ResultData<T> success() { ResultData<T> resultUtil = new ResultData<>(); resultUtil.setCode(SUCCESS_CODE); resultUtil.setMessage(SUCCESS_MESSAGE); return resultUtil; } public static <T> ResultData<T> success(T data) { ResultData<T> resultUtil = success(); resultUtil.setData(data); return resultUtil; } public static <T> ResultData<T> success(String message, T data) { ResultData<T> resultUtil = success(); resultUtil.setMessage(message); resultUtil.setData(data); return resultUtil; } public static <T> ResultData<T> success(Integer code, String message, T data) { ResultData<T> resultUtil = new ResultData<>(); resultUtil.setCode(code); resultUtil.setMessage(message); resultUtil.setData(data); return resultUtil; } public static <T> ResultData<T> success(Integer code, String message,Integer count, T data) { ResultData<T> resultUtil = new ResultData<>(); resultUtil.setCode(code); resultUtil.setMessage(message); resultUtil.setData(data); return resultUtil; } public static <T> ResultData<T> fail() { ResultData<T> resultUtil = new ResultData<>(); resultUtil.setCode(FAIL_CODE); resultUtil.setMessage(FAIL_MESSAGE); return resultUtil; } public static <T> ResultData<T> fail(T data) { ResultData<T> resultUtil = fail(); resultUtil.setData(data); return resultUtil; } public static <T> ResultData<T> fail(String message, T data) { ResultData<T> resultUtil = fail(); resultUtil.setMessage(message); resultUtil.setData(data); return resultUtil; } public static <T> ResultData<T> fail(Integer code, String message) { ResultData<T> resultUtil = fail(); resultUtil.setCode(code); resultUtil.setMessage(message); return resultUtil; } public static <T> ResultData<T> fail(Integer code, String message, T data) { ResultData<T> resultUtil = new ResultData<>(); resultUtil.setCode(code); resultUtil.setMessage(message); resultUtil.setData(data); return resultUtil; } public void setCode(int code){ this.code = code; } public int getCode(){ return this.code; } public void setMessage(String message){ this.message = message; } public String getMessage(){ return message; } public void setData(T data){ this.data = data; } public T getData(){ return data; } }
7.建立minio控制器
/** * minio相關介面 * * @author songwp * @date 2024/11/11 11:28 */ @RestController @RequestMapping("minio") public class MinioController { @Autowired MinioUtil minioUtil; /** * 檔案上傳 * * @param file 檔案 * @param bucket 桶名 * @param objectName 物件名 * @return 是否成功 * @throws Exception */ @RequestMapping(value = "/upload", method = RequestMethod.POST) public ResultData upload(@RequestParam MultipartFile file, @RequestParam String bucket, @RequestParam(required = false) String objectName) throws Exception { minioUtil.createBucket(bucket); if (objectName != null) { minioUtil.uploadFile(file.getInputStream(), bucket, objectName + "/" + file.getOriginalFilename()); } else { minioUtil.uploadFile(file.getInputStream(), bucket, file.getOriginalFilename()); } return ResultData.success(); } /** * 獲取檔案資訊 * @param bucket 桶名 * @return 是否成功 */ @RequestMapping(value = "/getFile", method = RequestMethod.GET) public ResultData getFile(@RequestParam ("bucket")String bucket){ try { List<Fileinfo> fileinfos = minioUtil.listFiles(bucket); return ResultData.success(fileinfos); } catch (Exception e) { throw new RuntimeException(e); } } /** * 檔案下載 * * @param bucket 桶名 * @param objectName 物件名 * @return 是否成功 */ @GetMapping("download") public ResultData download(@RequestParam("bucket") String bucket, @RequestParam("objectName") String objectName){ try { InputStream download = minioUtil.download(bucket, objectName); return ResultData.success(); } catch (Exception e) { throw new RuntimeException(e); } } /** * 獲取檔案資訊 * * @param bucket 桶名 * @param objectName 物件名 * @return 是否成功 */ @GetMapping("getObjectInfo") public ResultData getObjectInfo(@RequestParam("bucket") String bucket, @RequestParam("objectName") String objectName) throws Exception { String objectInfo = minioUtil.getObjectInfo(bucket, objectName); String objectStat = objectInfo.replaceAll("ObjectStat", ""); return ResultData.success(objectStat); } /** * 生成一個給HTTP GET請求用的presigned URL。 * * @param bucket 桶名 * @param objectName 物件名 * @return 是否成功 */ @GetMapping("getObjectUrl") public ResultData getObjectUrl(@RequestParam("bucket") String bucket, @RequestParam("objectName") String objectName) throws Exception { String url = minioUtil.getPresignedObjectUrl(bucket, objectName,7200); return ResultData.success(url); } /** * 列出所有的桶 */ @RequestMapping(value = "/listBuckets", method = RequestMethod.GET) public ResultData listBuckets() throws Exception { return ResultData.success(minioUtil.listBuckets()); } /** * 獲取minio中所有的檔案 */ @RequestMapping(value = "/listAllFile", method = RequestMethod.GET) public ResultData listAllFile() throws Exception { return ResultData.success(minioUtil.listAllFile()); } }
8.postman介面呼叫例項
9.最後檢視test-bucket桶中是否有剛才上傳的檔案就可以了。如果有則表明你的專案已經成功整合minio了