-
java项目结构如下:增加minioConfig配置,服务连接使用minioDto(包含endpoint,accesskey,serectkey)
-
minioDto代码如下:数据引用,从application.yml中的minio节点获取;
@Data
@Component
@ConfigurationProperties(prefix = "minio")
public class minioDto {
private String endpoint;
private String accesskey;
private String secretkwy;
}
application.yml中的minio节点如下:
minio:
endpoint: http://192.168.0.147:9000 //该地址为minio服务器的9000接口,api使用
accesskey: miniominio
secretkwy: miniominio
-
minioConfig代码如下: 此种设置,可以避免直接注册static的情况(static情况时minioDto为null,会造成接口调用失败)
/**
* @Description minio客户端单例类
* @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());
}
}
}
-
创建minioUtils工具类:根据需要,使用相关方法即可
/**
* Minio客户端工具类
*/
@SuppressWarnings("ALL")
public class MinioUtils {
private static final Logger log = LoggerFactory.getLogger(DbUtils.class);
/**
* 创建文件桶(建议租户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 + "-不存在");
}
//上传目录为当前日期时间
String datedir = DateUtils.format(new Date(),"yyyyMMddHHmmss");
MinioConfig.getMinioClient()
.uploadObject(
UploadObjectArgs.builder().bucket(bucket).object(datedir + "//" + 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();
//上传目录为当前日期时间
String datedir = DateUtils.format(new Date(),"yyyyMMdd");
PutObjectArgs objectArgs = PutObjectArgs.builder().bucket(bucketName).object(datedir + "//" + 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();
}
}
}
/**
* 自动创建桶并存储文件
*
* @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; // 生成时间戳防止重名
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;
}
/**
* 自动创建桶并存储文件
*
* @return
*/
public static String putObjectStream(MultipartFile file, String bucket) throws Exception {
//判断文件是否为空
if (null == file || 0 == file.getSize()) {
throw new ServiceException("上传minio文件服务器错误,上传文件为空");
}
boolean exsit = exitsBucket(bucket);
if (!exsit) {
//makeBucketPolicy(bucket);
log.error(bucket + "-不存在");
throw new ServiceException("minio文件服务器:" + bucket + " 桶不存在");
}
//文件名
String originalFilename = file.getOriginalFilename();
//新的文件名 = 时间戳_随机数.后缀名
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 对象名称
* @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 对象名称
* @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;
}
/**
* 获取单个桶中的所有文件对象名称
*
* @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;
}
/**
* 以流的形式获取一个文件对象
*
* @param bucket 桶名称
* @param objectName 对象名称
* @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();
// 获取文件对象
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();
}
}
}
/**
* 删除一个桶
*
* @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();
//有对象文件,则删除失败
if (item.size() > 0) {
return false;
}
}
// 删除`bucketName`存储桶,注意,只有存储桶为空时才能删除成功。
MinioConfig.getMinioClient().removeBucket(RemoveBucketArgs.builder().bucket(bucket).build());
found = exitsBucket(bucket);
return !found;
}
return false;
}
/**
* 获取某个桶下某个对象的URL
*
* @param bucket 桶名称
* @param objectName 对象名 (文件夹名 + 文件名)
* @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 "";
}
/**
* 根据文件路径得到预览文件绝对地址
*
* @param bucket 桶名称
* @param objectName 对象名 (文件夹名+文件名)
* @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);
// }
}
-
列出调用:上传,下载,删除接口代码:写到Controller页面即可
//上传文件到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 为数组格式 ,可以根据个人设置调整
@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服务的上传,下载,删除功能;
注:删除属于lazy方式,是延迟的,需要等会就可以看到minio服务器已经删除;
版权声明:本文为violetlength原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。