java之minio文件服務(wù)器的日常操作
1.java項(xiàng)目結(jié)構(gòu)
如下所示:
增加minioConfig配置,服務(wù)連接使用minioDto(包含endpoint,accesskey,serectkey)

2.minioDto代碼
如下所示:
數(shù)據(jù)引用,從application.yml中的minio節(jié)點(diǎn)獲取;
@Data
@Component
@ConfigurationProperties(prefix = "minio")
public class minioDto {
private String endpoint;
private String accesskey;
private String secretkwy;
}application.yml中的minio節(jié)點(diǎn)如下:
minio:
endpoint: http://192.168.0.147:9000 //該地址為minio服務(wù)器的9000接口,api使用
accesskey: miniominio
secretkwy: miniominio3.minioConfig代碼
如下所示:
此種設(shè)置,可以避免直接注冊(cè)static的情況(static情況時(shí)minioDto為null,會(huì)造成接口調(diào)用失?。?/p>
/**
* @Description minio客戶端單例類(lèi)
* @Date 2022-07-13 16:37
* @Author xie
*/
@Component
@Data
public class MinioConfig {
private static final Logger log = LoggerFactory.getLogger(DbUtils.class);
@Autowired
private minioDto dto;
private static MinioClient minioClient;
/**
* @description: 獲取minioClient
* @date 2021/6/22 16:55
* @return io.minio.MinioClient
*/
public static MinioClient getMinioClient(){
return minioClient;
}
/**
* 判斷 bucket是否存在
*
* @param bucketName:
* 桶名
* @return: boolean
* @date : 2020/8/16 20:53
*/
@SneakyThrows(Exception.class)
public static boolean bucketExists(String bucketName) {
return minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
}
/**
* 獲取全部bucket
*
* @param :
* @return: java.util.List<io.minio.messages.Bucket>
* @date : 2020/8/16 23:28
*/
@SneakyThrows(Exception.class)
public static List<Bucket> getAllBuckets() {
return minioClient.listBuckets();
}
/**
* 初始化minio配置
*
* @param :
* @return: void
* @date : 2020/8/16 20:56
*/
@PostConstruct
public void init() {
try {
minioClient = MinioClient.builder()
.endpoint(dto.getEndpoint())
.credentials(dto.getAccesskey(), dto.getSecretkwy())
.build();
} catch (Exception e) {
e.printStackTrace();
log.error("初始化minio配置異常: 【{}】", e.fillInStackTrace());
}
}
}4.創(chuàng)建minioUtils工具類(lèi)
根據(jù)需要,使用相關(guān)方法即可
/**
* Minio客戶端工具類(lèi)
*/
@SuppressWarnings("ALL")
public class MinioUtils {
private static final Logger log = LoggerFactory.getLogger(DbUtils.class);
/**
* 創(chuàng)建文件桶(建議租戶ID為桶的名稱)
*/
public static boolean exitsBucket(String bucket) {
boolean found = false;
try {
found = MinioConfig.getMinioClient().bucketExists(BucketExistsArgs.builder().bucket(bucket).build());
} catch (Exception e) {
log.error("create bucket is error", e);
}
return found;
}
public static String putObjectLocalFile(String bucket, String filename, String fileFullPath) {
try {
boolean bucketExsit = exitsBucket(bucket);
if (!bucketExsit) {
//makeBucketPolicy(bucket);
log.error(bucket + "-不存在");
throw new RuntimeException(bucket + "-不存在");
}
//上傳目錄為當(dāng)前日期時(shí)間
String datedir = DateUtils.format(new Date(),"yyyyMMddHHmmss");
MinioConfig.getMinioClient()
.uploadObject(
UploadObjectArgs.builder().bucket(bucket).object(datedir + "http://" + filename).filename(fileFullPath).build()
);
return MinioConfig.getMinioClient().getObjectUrl(bucket, filename);
} catch (Exception e) {
e.printStackTrace();
}
return "";
}
/**
*
* @param file
* @param bucketName
* @return
*/
public static String putObject(MultipartFile file, String bucketName){
InputStream inputStream = null;
try{
inputStream = file.getInputStream();
//上傳目錄為當(dāng)前日期時(shí)間
String datedir = DateUtils.format(new Date(),"yyyyMMdd");
PutObjectArgs objectArgs = PutObjectArgs.builder().bucket(bucketName).object(datedir + "http://" + file.getOriginalFilename())
.stream(inputStream, file.getSize(), -1).contentType(file.getContentType()).build();
MinioConfig.getMinioClient().putObject(objectArgs);
return MinioConfig.getMinioClient().getObjectUrl(bucketName, file.getOriginalFilename());
}
catch (Exception e){
e.printStackTrace();
return "";
}
finally {
try{
if (inputStream!=null){
inputStream.close();
}
}catch (Exception e){
e.printStackTrace();
}
}
}
/**
* 自動(dòng)創(chuàng)建桶并存儲(chǔ)文件
*
* @param inputStream
* @param fileName
* @param bucket
* @param fileSize
* @return
*/
public static String putObjectStream(InputStream inputStream, String fileName, String bucket, Long fileSize) {
try {
boolean bucketExsit = exitsBucket(bucket);
if (bucketExsit) {
//makeBucketPolicy(bucket);
log.error(bucket + "-不存在");
}
MinioConfig.getMinioClient().putObject(
PutObjectArgs.builder()
.bucket(bucket).object(fileName).stream(inputStream, fileSize, -1).build());
inputStream.close();
return MinioConfig.getMinioClient().getObjectUrl(bucket, fileName);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* @param bucket 桶名稱
* @param path 文件夾路徑 [doc/]
* @param file 要上傳的文件
* @param fileName 自定義文件名
* @return
*/
public static String putObject(String bucket, String path, MultipartFile file, String fileName) throws Exception {
if (!exitsBucket(bucket)) {
//makeBucketPolicy(bucket);
log.error(bucket + "-不存在");
}
InputStream inputStream = null;
try {
MinioConfig.getMinioClient().putObject(
PutObjectArgs.builder().bucket(bucket).object(path).stream(
new ByteArrayInputStream(new byte[]{}), 0, -1)
.build());
inputStream = file.getInputStream();
if (StringUtils.isEmpty(fileName)) {
fileName = file.getOriginalFilename();
}
InputStream in = file.getInputStream();
PutObjectOptions options = new PutObjectOptions(in.available(), -1);
options.setContentType(file.getContentType());
String objectName = path + System.currentTimeMillis() + "_" + fileName; // 生成時(shí)間戳防止重名
MinioConfig.getMinioClient().putObject(bucket, objectName, in, options);
file.getInputStream().close();
in.close();
return MinioConfig.getMinioClient().presignedGetObject(bucket, objectName);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (inputStream != null) {
inputStream.close();
}
}
return null;
}
/**
* 自動(dòng)創(chuàng)建桶并存儲(chǔ)文件
*
* @return
*/
public static String putObjectStream(MultipartFile file, String bucket) throws Exception {
//判斷文件是否為空
if (null == file || 0 == file.getSize()) {
throw new ServiceException("上傳minio文件服務(wù)器錯(cuò)誤,上傳文件為空");
}
boolean exsit = exitsBucket(bucket);
if (!exsit) {
//makeBucketPolicy(bucket);
log.error(bucket + "-不存在");
throw new ServiceException("minio文件服務(wù)器:" + bucket + " 桶不存在");
}
//文件名
String originalFilename = file.getOriginalFilename();
//新的文件名 = 時(shí)間戳_隨機(jī)數(shù).后綴名
assert originalFilename != null;
long now = System.currentTimeMillis() / 1000;
String fileName = DateUtils.format(new Date(),"yyyyMMdd")+"_"+ now + "_" + new Random().nextInt(1000) +
originalFilename.substring(originalFilename.lastIndexOf("."));
String fileHeader = null;
try {
InputStream inputStream = file.getInputStream();
//boolean bucketExsit = exitsBucket(bucket);
//if (bucketExsit) {
// MinioClientSingleton.getMinioClient().makeBucket(MakeBucketArgs.builder()
// .bucket(bucket)
// .build());
//}
MinioConfig.getMinioClient().putObject(
PutObjectArgs.builder().bucket(bucket).object(fileName).stream(
inputStream, file.getSize(), -1)
.contentType(file.getContentType())
.build());
//MinioClientSingleton.getMinioClient().putObject(
// PutObjectArgs.builder()
// .bucket(bucket).object(file.getOriginalFilename()).stream(inputStream, inputStream.available(), -1).build());
inputStream.close();
return MinioConfig.getMinioClient().getObjectUrl(bucket, fileName);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
//private static void makeBucketPolicy(String bucket) throws ErrorResponseException, InsufficientDataException, InternalException, InvalidBucketNameException, InvalidKeyException, InvalidResponseException, IOException, NoSuchAlgorithmException, RegionConflictException, ServerException, XmlParserException {
// String policyJsonBuilder = "{\n" +
// " "Statement": [\n" +
// " {\n" +
// " "Action": [\n" +
// " "s3:GetBucketLocation",\n" +
// " "s3:ListBucket"\n" +
// " ],\n" +
// " "Effect": "Allow",\n" +
// " "Principal": "*",\n" +
// " "Resource": "arn:aws:s3:::" + bucket + ""\n" +
// " },\n" +
// " {\n" +
// " "Action": "s3:GetObject",\n" +
// " "Effect": "Allow",\n" +
// " "Principal": "*",\n" +
// " "Resource": "arn:aws:s3:::" + bucket + "/*"\n" +
// " }\n" +
// " ],\n" +
// " "Version": "2012-10-17"\n" +
// "}\n";
// MinioClientSingleton.getMinioClient().makeBucket(MakeBucketArgs.builder()
// .bucket(bucket)
// .build());
// //noinspection deprecation
// MinioClientSingleton.getMinioClient().setBucketPolicy(bucket, policyJsonBuilder);
//}
/**
* 查詢所有桶文件
*
* @return
*/
public static List<Bucket> getListBuckets() {
try {
return MinioConfig.getMinioClient().listBuckets();
} catch (Exception e) {
e.printStackTrace();
}
return Collections.emptyList();
}
/**
* 刪除文件
*
* @param bucket 桶名稱
* @param objectName 對(duì)象名稱
* @return boolean
*/
public static boolean removeObject(String bucket, String objectName) {
try {
boolean exsit = exitsBucket(bucket);
if (exsit) {
// 從mybucket中刪除myobject。removeobjectargs.builder().bucket(bucketname).object(objectname).build()
MinioConfig.getMinioClient().removeObject(RemoveObjectArgs.builder().bucket(bucket).object(objectName).build());
return true;
}
} catch (Exception e) {
log.error("removeObject", e);
}
return false;
}
/**
* 批量刪除文件
*
* @param bucket 桶名稱
* @param objectNames 對(duì)象名稱
* @return boolean
*/
public static boolean removeObjects(String bucket, List<String> objectNames) {
boolean exsit = exitsBucket(bucket);
if (exsit) {
try {
List<DeleteObject> deleteObjects = new LinkedList<>();
for (String objectName : objectNames) {
deleteObjects.add(new DeleteObject(objectName));
}
Iterable<Result<DeleteError>> results = MinioConfig.getMinioClient().removeObjects(
RemoveObjectsArgs.builder()
.bucket(bucket)
.objects(deleteObjects)
.build()
);
for (Result<DeleteError> result : results) {
DeleteError error = result.get();
log.error(
"Error in deleting object " + error.objectName() + "; " + error.message());
}
return true;
} catch (Exception e) {
log.error("removeObject", e);
}
}
return false;
}
/**
* 獲取單個(gè)桶中的所有文件對(duì)象名稱
*
* @param bucket 桶名稱
* @return {@link List}<{@link String}>
*/
public static List<String> getBucketObjectName(String bucket) {
boolean exsit = exitsBucket(bucket);
if (exsit) {
List<String> listObjetcName = new ArrayList<>();
try {
Iterable<Result<Item>> myObjects = MinioConfig.getMinioClient().listObjects(ListObjectsArgs.builder().bucket(bucket).build());
for (Result<Item> result : myObjects) {
Item item = result.get();
listObjetcName.add(item.objectName());
}
return listObjetcName;
} catch (Exception e) {
e.printStackTrace();
}
}
return null;
}
/**
* 以流的形式獲取一個(gè)文件對(duì)象
*
* @param bucket 桶名稱
* @param objectName 對(duì)象名稱
* @return {@link InputStream}
*/
public static InputStream getObjectInputStream(String bucket, String objectName) {
boolean exsit = exitsBucket(bucket);
if (exsit) {
try {
ObjectStat objectStat = MinioConfig.getMinioClient().statObject(StatObjectArgs.builder().bucket(bucket).object(objectName).build());
if (objectStat.length() > 0) {
// 獲取objectName的輸入流。
return MinioConfig.getMinioClient().getObject(GetObjectArgs.builder().bucket(bucket).object(objectName).build());
}
} catch (Exception e) {
e.printStackTrace();
}
}
return null;
}
/**
* 文件下載
* @param fileName 文件名
* @param delete 是否刪除
* @throws IOException
*/
public static InputStream fileDownload(String bucketName, String fileName, HttpServletResponse response) {
MinioClient minioClient = MinioConfig.getMinioClient();
if (minioClient == null) {
return null;
}
InputStream inputStream = null;
OutputStream outputStream = null;
try {
if (StringUtils.isBlank(fileName)) {
response.setHeader("Content-type", "text/html;charset=UTF-8");
String data = "文件下載失敗";
OutputStream ps = response.getOutputStream();
ps.write(data.getBytes("UTF-8"));
return null;
}
outputStream = response.getOutputStream();
// 獲取文件對(duì)象
inputStream =MinioConfig.getMinioClient().getObject(GetObjectArgs.builder().bucket(bucketName).object(fileName).build());
byte buf[] = new byte[1024];
int length = 0;
response.reset();
response.setHeader("Content-Disposition", "attachment;filename=" +
URLEncoder.encode(fileName.substring(fileName.lastIndexOf("/") + 1), "UTF-8"));
response.setContentType("application/octet-stream");
response.setCharacterEncoding("UTF-8");
// 輸出文件
while ((length = inputStream.read(buf)) > 0) {
outputStream.write(buf, 0, length);
}
inputStream.close();
return inputStream;
} catch (Throwable ex) {
response.setHeader("Content-type", "text/html;charset=UTF-8");
String data = "文件下載失敗";
try {
OutputStream ps = response.getOutputStream();
ps.write(data.getBytes("UTF-8"));
}catch (IOException e){
e.printStackTrace();
}
return null;
} finally {
try {
outputStream.close();
if (inputStream != null) {
inputStream.close();
}}catch (IOException e){
e.printStackTrace();
}
}
}
/**
* 刪除一個(gè)桶
*
* @param bucket 桶名稱
*/
public static boolean removeBucket(String bucket) throws Exception {
// 刪除之前先檢查`my-bucket`是否存在。
boolean found = exitsBucket(bucket);
if (found) {
Iterable<Result<Item>> myObjects = MinioConfig.getMinioClient().listObjects(ListObjectsArgs.builder().bucket(bucket).build());
for (Result<Item> result : myObjects) {
Item item = result.get();
//有對(duì)象文件,則刪除失敗
if (item.size() > 0) {
return false;
}
}
// 刪除`bucketName`存儲(chǔ)桶,注意,只有存儲(chǔ)桶為空時(shí)才能刪除成功。
MinioConfig.getMinioClient().removeBucket(RemoveBucketArgs.builder().bucket(bucket).build());
found = exitsBucket(bucket);
return !found;
}
return false;
}
/**
* 獲取某個(gè)桶下某個(gè)對(duì)象的URL
*
* @param bucket 桶名稱
* @param objectName 對(duì)象名 (文件夾名 + 文件名)
* @return
*/
public static String getBucketObject(String bucket, String objectName) throws Exception {
// 刪除之前先檢查`my-bucket`是否存在。
boolean found = exitsBucket(bucket);
if (found) {
return MinioConfig.getMinioClient().getObjectUrl(bucket, objectName);
}
return "";
}
/**
* 根據(jù)文件路徑得到預(yù)覽文件絕對(duì)地址
*
* @param bucket 桶名稱
* @param objectName 對(duì)象名 (文件夾名+文件名)
* @return
*/
public String getPreviewFileUrl(String bucket, String objectName) {
try {
return MinioConfig.getMinioClient().presignedGetObject(bucket, objectName);
} catch (Exception e) {
e.printStackTrace();
return "";
}
}
// public static void main(String[] args) {
//
// String bucket = "my-bucket-test01";
// String filename = System.currentTimeMillis() + "截圖.png";
// String fileFullPath = "C:\\Users\\Administrator\\Desktop\\截圖.png";
//
// String fileUrl = putObjectLocalFile(bucket, filename, fileFullPath);
// System.out.println(fileUrl);
// }
}5.列出調(diào)用
上傳,下載,刪除接口代碼:寫(xiě)到Controller頁(yè)面即可
//上傳文件到minio
@PostMapping(value = "fileUpload")
public AjaxResult fileUpload( MultipartFile file){
try{
String sUrl = MinioUtils.putObject(file,"buckettest");
if(!sUrl.equals("")){
return AjaxResult.success("上傳成功。",sUrl);
}
else{
return AjaxResult.error("上傳失敗。");
}
}
catch (Exception e){
e.printStackTrace();
return AjaxResult.error("上傳失敗。");
}
}
//刪除文件 filelist 為數(shù)組格式 ,可以根據(jù)個(gè)人設(shè)置調(diào)整
@PostMapping(value = "/deleteFile")
public AjaxResult deleteFile(@RequestBody HdRequestBody filelist){
Object list = filelist.getValueFromData("filelist");
List<String> fileList = new ArrayList<>();
if (list instanceof ArrayList<?>) {
for (Object o : (List<?>) list) {
fileList.add(String.class.cast(o));
}
}
boolean flag = MinioUtils.removeObjects("buckettest",fileList);
return flag == true ? AjaxResult.success("刪除成功") : AjaxResult.error("刪除失敗");
}
/**
* 下載文件
* @param fileName
* @param response
* @return
*/
@PostMapping(value = "/downloadFile")
public String downloadFile(@RequestParam String fileName, HttpServletResponse response) {
return MinioUtils.fileDownload("buckettest",fileName,response) != null ? "下載成功" : "下載失敗";
}以上操作后,即可解決minio服務(wù)的上傳,下載,刪除功能;
注:刪除屬于lazy方式,是延遲的,需要等會(huì)就可以看到minio服務(wù)器已經(jīng)刪除;
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Java?Object類(lèi)和包裝類(lèi)深入解讀
Object類(lèi)是一個(gè)特殊的類(lèi),是所有類(lèi)的父類(lèi),如果一個(gè)類(lèi)沒(méi)有用extends明確指出繼承于某個(gè)類(lèi),那么它默認(rèn)繼承Object類(lèi),所謂包裝類(lèi),就是能夠直接將簡(jiǎn)單類(lèi)型的變量表示為一個(gè)類(lèi),在執(zhí)行變量類(lèi)型的相互轉(zhuǎn)換時(shí),我們會(huì)大量使用這些包裝類(lèi)2022-02-02
Java實(shí)現(xiàn)定時(shí)任務(wù)最簡(jiǎn)單的3種方法
幾乎在所有的項(xiàng)目中,定時(shí)任務(wù)的使用都是不可或缺的,如果使用不當(dāng)甚至?xí)斐少Y損,下面這篇文章主要給大家介紹了關(guān)于Java實(shí)現(xiàn)定時(shí)任務(wù)最簡(jiǎn)單的3種方法,本文通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-06-06
java使用wait和notify實(shí)現(xiàn)線程通信
這篇文章主要為大家詳細(xì)介紹了java如何使用wait和notify實(shí)現(xiàn)線程之間通信,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2023-10-10
java鏈?zhǔn)絼?chuàng)建json對(duì)象的實(shí)現(xiàn)
本文主要介紹了java中如何通過(guò)最簡(jiǎn)單的方式實(shí)現(xiàn)鏈?zhǔn)絼?chuàng)建json對(duì)象,解決創(chuàng)建json代碼臃腫的問(wèn)題,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-02-02
如何在SpringBoot項(xiàng)目中集成SpringSecurity進(jìn)行權(quán)限管理
在本文中,我們將討論如何在Spring?Boot項(xiàng)目中集成權(quán)限管理,我們將使用Spring?Security框架,這是一個(gè)專(zhuān)門(mén)用于實(shí)現(xiàn)安全性功能的框架,包括認(rèn)證和授權(quán),需要的朋友可以參考下2023-07-07
對(duì)象存儲(chǔ)服務(wù)MinIO快速入門(mén)(集成項(xiàng)目的詳細(xì)過(guò)程)
MinIO是一個(gè)開(kāi)源的對(duì)象存儲(chǔ)服務(wù),支持多種操作系統(tǒng),配置簡(jiǎn)單且性能高,它使用糾刪碼進(jìn)行數(shù)據(jù)保護(hù),可以容忍硬件故障,MinIO支持多種語(yǔ)言的SDK和豐富的API,本文介紹對(duì)象存儲(chǔ)服務(wù)MinIO快速入門(mén),感興趣的朋友一起看看吧2025-03-03

