SpringBoot集成Minio文件系统
SpringBoot集成Minio文件服务
1、安装Minio
2、pom文件添加依赖
<!-- 操作minio的java客户端-->
<dependency>
<groupId>io.minio</groupId>
<artifactId>minio</artifactId>
<version>8.2.1</version>
</dependency>
依赖可以官方文档里找: https://docs.min.io/docs/java-client-quickstart-guide.html
注意:版本太高可能会因为版本不匹配导致启动报错
3、yml添加配置
#minio配置
minio:
endpoint: http://localhost:9000 #MinIO服务所在地址
accessKey: xxxxxx #key就是docker初始化是设置的,密钥相同
secretKey: xxxxxxxx #访问的秘钥
bucketName: xxxxx #存储桶名称
4、创建minio的配置类
使用配置属性绑定进行参数绑定,并初始化一个minio client对象放入容器中。
@Slf4j
@Configuration
public class MinioConfig {
@Value("${minio.endpoint}")
private String endpoint;
@Value("${minio.bucketName}")
private String bucketName;
@Value("${minio.accessKey}")
private String accessKey;
@Value("${minio.secretKey}")
private String secretKey;
@Bean(name = "minioClient")
public MinioClient minioClient() {
return MinioClient.builder()
.endpoint(endpoint)
.credentials(accessKey, secretKey)
.build();
}
}
5、创建操作api的工具类
@Slf4j
public class MinioUtil {
private static MinioClient minioClient;
static {
minioClient = SpringUtil.getBean("minioClient", MinioClient.class);
}
/**
* 创建一个桶,当bucket已存在时直接跳过,不存在时创建
* @param bucket
* @return void
* @author zhongyufeng
* @date 2022/7/28 16:51
*/
public static 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 static void deleteBucket(String bucket) throws Exception {
minioClient.removeBucket(RemoveBucketArgs.builder().bucket(bucket).build());
}
/**
* 上传一个文件
*/
public static void uploadFile(InputStream stream, String bucket, String objectName) throws Exception {
minioClient.putObject(PutObjectArgs.builder().bucket(bucket).object(objectName)
.stream(stream, -1, 10485760).build());
}
/**
* 列出所有的桶
*/
public static List<String> listBuckets() throws Exception {
List<Bucket> list = minioClient.listBuckets();
return Optional.ofNullable(list).orElse(new ArrayList<>(0)).stream().map(Bucket::name).collect(Collectors.toList());
}
/**
* 列出一个桶中的所有文件和目录
*/
public static List<FileInfo> listFiles(String bucket) {
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());
infos.add(info);
} catch (Exception e) {
e.printStackTrace();
}
});
return infos;
}
/**
* 下载一个文件
*/
public static InputStream download(String bucket, String objectName) throws Exception {
InputStream stream = minioClient.getObject(
GetObjectArgs.builder().bucket(bucket).object(objectName).build());
return stream;
}
/**
* 删除一个对象
*/
public static void deleteObject(String bucket, String objectName) throws Exception {
minioClient.removeObject(RemoveObjectArgs.builder().bucket(bucket).object(objectName).build());
}
/**
* 获取minio文件的下载或者预览地址
* @param bucket
* @param objectName
* @return java.lang.String
* @author zhongyufeng
* @date 2022/7/28 18:43
*/
public static String getPreviewFileUrl(String bucket, String objectName) throws Exception {
return minioClient.getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder().bucket(bucket).object(objectName).method(Method.GET).build());
}
}
FileInfo
@Data
public class FileInfo {
private String filename;
private Boolean directory;
}
6、接口测试
@CrossOrigin
@RestController
@RequestMapping("/demo/minio")
@AllArgsConstructor
@Slf4j
public class MinioController {
/**
* 获取所有的桶名称
* @param
* @return com.zyf.zboot.common.core.result.R<?>
* @author zhongyufeng
* @date 2022/7/28 17:19
*/
@GetMapping("/listBuckets")
public R<?> listBuckets() throws Exception {
List<String> list = MinioUtil.listBuckets();
return R.ok(list);
}
/**
* 创建桶
* @param bucketName 桶名称
* @return com.zyf.zboot.common.core.result.R<?>
* @author zhongyufeng
* @date 2022/7/28 17:20
*/
@PutMapping("/createBucket/{bucketName}")
public R<?> createBucket(@PathVariable("bucketName") String bucketName) {
try {
MinioUtil.createBucket(bucketName);
} catch (Exception e) {
log.error("创建桶失败===========>{}", ExceptionUtil.getMessage(e));
return R.error("创建桶失败");
}
return R.ok();
}
/**
* 删除桶
* @param bucketName 桶名称
* @return com.zyf.zboot.common.core.result.R<?>
* @author zhongyufeng
* @date 2022/7/28 17:20
*/
@DeleteMapping("/deleteBucket/{bucketName}")
public R<?> deleteBucket(@PathVariable("bucketName") String bucketName) {
try {
MinioUtil.deleteBucket(bucketName);
} catch (Exception e) {
log.error("删除桶失败===========>{}", ExceptionUtil.getMessage(e));
return R.error("删除桶失败");
}
return R.ok();
}
/**
* 递归列出一个桶中的所有文件和目录
* @param bucket 桶名称
* @return com.zyf.zboot.common.core.result.R<?>
* @author zhongyufeng
* @date 2022/7/28 17:24
*/
@GetMapping("/listFiles/{bucket}")
public R<?> listFiles(@PathVariable("bucket") String bucket){
return R.ok(MinioUtil.listFiles(bucket));
}
/**
* 上传文件
* @param bucket 桶名称
* @param url 文件路径
* @param uploadFile 文件
* @return com.zyf.zboot.common.core.result.R<?>
* @author zhongyufeng
* @date 2022/7/28 17:20
*/
@PostMapping("/uploadFile/{bucket}")
public R<?> uploadFile(@PathVariable("bucket") String bucket,
@RequestParam("url") String url,
@RequestParam("file") MultipartFile uploadFile) {
try {
//先创建(桶不存在时才会创建,存在则不作操作)
MinioUtil.createBucket(bucket);
MinioUtil.uploadFile(uploadFile.getInputStream(), bucket, url + "/" + uploadFile.getOriginalFilename());
} catch (Exception e) {
log.error("上传文件失败===========>{}", ExceptionUtil.getMessage(e));
return R.error("上传文件失败");
}
return R.ok();
}
/**
* 下载一个文件
* @param bucket 桶名称
* @param objectName 文件名(全路径)
* @param response
* @return void
* @author zhongyufeng
* @date 2022/7/28 17:32
*/
@GetMapping("/downloadFile/{bucket}")
public void downloadFile(@PathVariable("bucket") String bucket,
@RequestParam("objectName") String objectName,
HttpServletResponse response) throws Exception {
InputStream stream = MinioUtil.download(bucket, objectName);
ServletOutputStream output = response.getOutputStream();
response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(objectName.substring(objectName.lastIndexOf("/") + 1), "UTF-8"));
response.setContentType("application/octet-stream");
response.setCharacterEncoding("UTF-8");
IOUtils.copy(stream, output);
}
/**
* 获取minio文件的下载或者预览地址
* 取决于调用本方法的方法中的PutObjectOptions对象有没有设置contentType
*
* @param bucket: 桶名
* @param objectName: 文件名
*/
@GetMapping("/getPreviewFileUrl/{bucket}")
public R<?> getPreviewFileUrl(@PathVariable("bucket") String bucket, @RequestParam("objectName") String objectName) {
String previewFileUrl = null;
try {
previewFileUrl = MinioUtil.getPreviewFileUrl(bucket, objectName);
} catch (Exception e) {
log.error("获取文件预览地址失败======>{}", ExceptionUtil.getMessage(e));
return R.error("获取文件预览地址失败");
}
return R.ok(previewFileUrl);
}
/**
* 删除一个文件
* @param bucket 桶名称
* @param objectName 文件名称(全路径)
* @return com.zyf.zboot.common.core.result.R<?>
* @author zhongyufeng
* @date 2022/7/28 17:35
*/
@DeleteMapping("/deleteFile/{bucket}")
@ResponseBody
public R<?> deleteFile(@PathVariable("bucket") String bucket, @RequestParam("objectName") String objectName) throws Exception {
MinioUtil.deleteObject(bucket, objectName);
return R.ok();
}
}
7、关于预览
如果桶的权限设置为public 则可以直接通过 http://IP:端口/bucket/objectName 预览/下载文件
但是如果桶的权限设置为private时,则无法直接访问,需要通过这个方法获取访问的url,并且有方式时间限制,默认为7天,最大时间也是7天
String url = minioClient.getPresignedObjectUrl(
GetPresignedObjectUrlArgs.builder()
.method(Method.GET)
.bucket(bucket)
.object(objectName)
.expiry(2, TimeUnit.HOURS)
.build());
本文是原创文章,采用 CC BY-NC-ND 4.0 协议,完整转载请注明来自 奇怪的阿峰
评论
匿名评论
隐私政策
你无需删除空行,直接评论以获取最佳展示效果