直接docker润起来(其实是我用服务器运行一早上,没成功.......................)
docker run \ -p 9000:9000 \ -p 9001:9001 \ --user $(id -u):$(id -g) \ --name minio1 \ -e "MINIO_ROOT_USER=ROOTUSER" \ -e "MINIO_ROOT_PASSWORD=CHANGEME123" \ -v ${HOME}/minio/data:/data \ quay.io/minio/minio server /data --console-address ":9001"
9000是上传和下载的地址,就是提供给其他服务调用的地址。
9001是minio的管理页面的地址,在上面可以管理minio:
然后就是java调用:
配置:
server: port: 8001 minio: endpoint: http://192.168.126.134:9000 #Minio地址 bucketName: backupstest #堆名 accessKey: ROOTUSER #name secretKey: CHANGEME123 #密码
config文件:
package com.example.miniodome.comfig; import io.minio.MinioClient; import lombok.Data; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Data @Configuration @ConfigurationProperties(prefix = "minio") public class MinioConfig { private String endpoint; private String accessKey; private String secretKey; private String bucketName; @Bean public MinioClient minioClient() { return MinioClient.builder().endpoint(endpoint).credentials(accessKey, secretKey).build(); } }
package com.example.miniodome.util; import com.example.miniodome.comfig.MinioConfig; import io.micrometer.common.util.StringUtils; import io.minio.*; import io.minio.http.Method; import io.minio.messages.Bucket; import io.minio.messages.Item; import jakarta.annotation.Resource; import jakarta.servlet.ServletOutputStream; import jakarta.servlet.http.HttpServletResponse; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.springframework.util.FastByteArrayOutputStream; import org.springframework.web.multipart.MultipartFile; import java.time.LocalDate; import java.util.ArrayList; import java.util.List; import java.util.UUID; @Component @Slf4j public class MinioUtil { @Autowired private MinioConfig prop; @Resource private MinioClient minioClient; /** * 查看存储bucket是否存在 * * @return boolean */ public Boolean bucketExists(String bucketName) { Boolean found; try { found = minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build()); } catch (Exception e) { e.printStackTrace(); return false; } return found; } /** * 创建存储bucket * * @return Boolean */ public Boolean makeBucket(String bucketName) { try { minioClient.makeBucket(MakeBucketArgs.builder() .bucket(bucketName) .build()); } catch (Exception e) { e.printStackTrace(); return false; } return true; } /** * 删除存储bucket * * @return Boolean */ public Boolean removeBucket(String bucketName) { try { minioClient.removeBucket(RemoveBucketArgs.builder() .bucket(bucketName) .build()); } catch (Exception e) { e.printStackTrace(); return false; } return true; } /** * 获取全部bucket */ public List<Bucket> getAllBuckets() { try { List<Bucket> buckets = minioClient.listBuckets(); return buckets; } catch (Exception e) { e.printStackTrace(); } return null; } /** * 文件上传 * * @param file 文件 * @return Boolean */ public String upload(MultipartFile file) { String originalFilename = file.getOriginalFilename(); if (StringUtils.isBlank(originalFilename)) { throw new RuntimeException(); } String fileName = UUID.randomUUID() + originalFilename.substring(originalFilename.lastIndexOf(".")); String objectName = LocalDate.now().toString() + fileName; try { PutObjectArgs objectArgs = PutObjectArgs.builder().bucket(prop.getBucketName()).object(objectName) .stream(file.getInputStream(), file.getSize(), -1).contentType(file.getContentType()).build(); //文件名称相同会覆盖 minioClient.putObject(objectArgs); } catch (Exception e) { e.printStackTrace(); return null; } return objectName; } public static void main(String[] args) { System.out.println(UUID.randomUUID()); } /** * 预览图片 * * @param fileName * @return */ public String preview(String fileName) { // 查看文件地址 GetPresignedObjectUrlArgs build = new GetPresignedObjectUrlArgs().builder().bucket(prop.getBucketName()).object(fileName).method(Method.GET).build(); try { String url = minioClient.getPresignedObjectUrl(build); return url; } catch (Exception e) { e.printStackTrace(); } return null; } /** * 文件下载 * * @param fileName 文件名称 * @param res response * @return Boolean */ public void download(String fileName, HttpServletResponse res) { GetObjectArgs objectArgs = GetObjectArgs.builder().bucket(prop.getBucketName()) .object(fileName).build(); try (GetObjectResponse response = minioClient.getObject(objectArgs)) { byte[] buf = new byte[1024]; int len; try (FastByteArrayOutputStream os = new FastByteArrayOutputStream()) { while ((len = response.read(buf)) != -1) { os.write(buf, 0, len); } os.flush(); byte[] bytes = os.toByteArray(); res.setCharacterEncoding("utf-8"); // 设置强制下载不打开 // res.setContentType("application/force-download"); res.addHeader("Content-Disposition", "attachment;fileName=" + fileName); try (ServletOutputStream stream = res.getOutputStream()) { stream.write(bytes); stream.flush(); } } } catch (Exception e) { e.printStackTrace(); } } /** * 查看文件对象 * * @return 存储bucket内文件对象信息 */ public List<Item> listObjects() { Iterable<Result<Item>> results = minioClient.listObjects( ListObjectsArgs.builder().bucket(prop.getBucketName()).build()); List<Item> items = new ArrayList<>(); try { for (Result<Item> result : results) { items.add(result.get()); } } catch (Exception e) { e.printStackTrace(); return null; } return items; } /** * 删除 * * @param fileName * @return * @throws Exception */ public boolean remove(String fileName) { try { minioClient.removeObject(RemoveObjectArgs.builder().bucket(prop.getBucketName()).object(fileName).build()); } catch (Exception e) { return false; } return true; } }
package com.example.miniodome.util; import lombok.Data; /** * @program: springCloudAlibaba * @author: quxiao * @create: 2024-03-07 17:21 **/ @Data public class MyResult<T> { private static final String SUCCESS_CODE = "200"; private static final String SUCCESS_MSG = "操作成功"; private static final String FALL_CODE = "500"; private static final String FALL_MSG = "操作失败"; private String msgName; private String msgCode; private Boolean status; private T data; public static MyResult success(Object data) { MyResult result = new MyResult(); result.setData(data); result.setStatus(true); result.setMsgCode(SUCCESS_CODE); result.setMsgName(SUCCESS_MSG); return result; } public static MyResult success() { MyResult result = new MyResult(); result.setStatus(true); result.setMsgCode(SUCCESS_CODE); result.setMsgName(SUCCESS_MSG); return result; } public static MyResult fail() { MyResult result = new MyResult(); result.setStatus(false); result.setMsgCode(FALL_CODE); result.setMsgName(FALL_MSG); return result; } public static MyResult fail(Object data) { MyResult result = new MyResult(); result.setStatus(false); result.setMsgCode(FALL_CODE); result.setMsgName(FALL_MSG); result.setData(data); return result; } }
package com.example.miniodome.controller; import com.example.miniodome.comfig.MinioConfig; import com.example.miniodome.util.MinioUtil; import com.example.miniodome.util.MyResult; import io.minio.messages.Bucket; import jakarta.servlet.http.HttpServletResponse; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; import java.util.List; //@Api(tags = "文件相关接口") @Slf4j @RestController public class FileController { @Autowired private MinioUtil minioUtil; @Autowired private MinioConfig prop; // @ApiOperation(value = "查看存储bucket是否存在") @GetMapping("/bucketExists") public MyResult bucketExists(String bucketName) { return MyResult.success(minioUtil.bucketExists(bucketName)); } // @ApiOperation(value = "创建存储bucket") @GetMapping("/makeBucket") public MyResult makeBucket(String bucketName) { minioUtil.makeBucket(bucketName); return MyResult.success(); } // @ApiOperation(value = "删除存储bucket") @GetMapping("/removeBucket") public MyResult removeBucket(String bucketName) { minioUtil.removeBucket(bucketName); return MyResult.success(); } // @ApiOperation(value = "获取全部bucket") @GetMapping("/getAllBuckets") public MyResult<List<Bucket>> getAllBuckets() { List<Bucket> allBuckets = minioUtil.getAllBuckets(); return MyResult.success(allBuckets); } // @ApiOperation(value = "文件上传返回url") @PostMapping("/upload") public MyResult<String> upload(@RequestParam(value = "file") MultipartFile file) { String objectName = minioUtil.upload(file); if (null != objectName) { return MyResult.success(prop.getEndpoint() + "/" + prop.getBucketName() + "/" + objectName); } return MyResult.fail(); } // @ApiOperation(value = "图片/视频预览") @GetMapping("/preview") public MyResult preview(@RequestParam("fileName") String fileName) { return MyResult.success(minioUtil.preview(fileName)); } // @ApiOperation(value = "文件下载") @GetMapping("/download/{fileName}") public MyResult download(@PathVariable("fileName") String fileName, HttpServletResponse res) { minioUtil.download(fileName, res); return MyResult.success(); } // @ApiOperation(value = "删除文件", notes = "根据url地址删除文件") @PostMapping("/delete") public MyResult remove(String url) { String objName = url.substring(url.lastIndexOf(prop.getBucketName() + "/") + prop.getBucketName().length() + 1); minioUtil.remove(objName); return MyResult.success(); } }
这里可以将提前生成的前缀存入数据库中,对应文件名。
然后调用下载的时候,就将文件名替换为真正的文件名,而不是用来标识准确文件的uuid前缀:
然后另一个就是,可以直接访问minio的资源,调用上传接口返回的url,但是需要在minio控制页面中配置: