最近公司需要搭建一个文件服务,废话不多说,直接上代码。
minio的安装及启动
1.安装
wget https://dl.minio.io/server/minio/release/linux-amd64/minio
2.赋予minio权限以及启动
权限命令:chmod +x minio
启动命令:./minio server /home/minio/data (/home/minio/data 为你存放静态文件的目录)
推荐:
后台运行命令:nohup /usr/local/minio server /home/minio/data > /home/minio/data/minio.log 2>&1 &
启动信息里面有地址:
地址启动:默认用户名密码:minioadmin/minioadmin
java 使用:
package com.smartnest.minio.config; import com.smartnest.minio.core.MinioTemplate; import io.minio.errors.MinioException; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; /** * @author lvs * @date 2020/08/04 11:38 */ @Configuration public class MinioConfig { @Bean public MinioTemplate minioTemplate(@Value("${minio.endPoint}") String endPoint, @Value("${minio.accessKey}") String accessKey, @Value("${minio.secretKey}") String secretKey, @Value("${minio.partSize}") int partSize) throws MinioException { return new MinioTemplate(endPoint, accessKey, secretKey, partSize); } }
package com.smartnest.minio.core; import io.minio.*; import io.minio.http.Method; import io.minio.messages.Bucket; import io.minio.messages.Item; import lombok.AllArgsConstructor; import lombok.SneakyThrows; import org.springframework.web.multipart.MultipartFile; import sun.misc.BASE64Decoder; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.List; import java.util.Optional; import java.util.concurrent.TimeUnit; /** * minio template * @author lvs * @date 2020/08/04 16:06 */ @AllArgsConstructor public class MinioTemplate { private String endpoint; private String accessKey; private String secretKey; private int partSize; private MinioClient client; @SneakyThrows public MinioTemplate(String endpoint, String accessKey, String secretKey, int partSize) { this.endpoint = endpoint; this.accessKey = accessKey; this.secretKey = secretKey; this.partSize = partSize; this.client = MinioClient.builder().endpoint(endpoint).credentials(accessKey, secretKey).build(); } /** * 创建bucket * * @param bucketName bucket名称 */ public void createBucket(String bucketName) throws Exception { if (!client.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build())) { client.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build()); } } /** * 获取全部bucket * <p> * https://docs.minio.io/cn/java-client-api-reference.html#listBuckets */ public List<Bucket> getAllBuckets() throws Exception { return client.listBuckets(); } /** * 根据bucketName获取信息 * @param bucketName bucket名称 */ public Optional<Bucket> getBucket(String bucketName) throws Exception { return client.listBuckets().stream().filter(b -> b.name().equals(bucketName)).findFirst(); } /** * 根据bucketName删除信息 * @param bucketName bucket名称 */ public void removeBucket(String bucketName) throws Exception { client.removeBucket(RemoveBucketArgs.builder().bucket(bucketName).build()); } /** * 分区上传文件 * @param bucketName bucket名称 * @param objectName 文件名称 * @param stream 文件流 * @param size 文件大小 */ public String putObject(String bucketName, String objectName, InputStream stream, Long size) throws Exception{ PutObjectArgs putObjectArgs = PutObjectArgs.builder() .bucket(bucketName) .object(objectName) .stream(stream, size, partSize) .build(); ObjectWriteResponse objectWriteResponse = client.putObject(putObjectArgs); return objectWriteResponse.object(); } /** * 根据文件前置查询文件 * * @param bucketName bucket名称 * @param prefix 前缀 * @param recursive 是否递归查询 * @return MinioItem 列表 */ public List<Item> getAllObjectsByPrefix(String bucketName, String prefix, boolean recursive) throws Exception { List<Item> objectList = new ArrayList<>(); ListObjectsArgs listObjectsArgs = ListObjectsArgs.builder() .bucket(bucketName) .prefix(prefix) .recursive(recursive) .build(); Iterable<Result<Item>> objectsIterator = client .listObjects(listObjectsArgs); while (objectsIterator.iterator().hasNext()) { objectList.add(objectsIterator.iterator().next().get()); } return objectList; } /** * 获取文件外链 * 这里的 method 方法决定最后链接是什么请求获得 * expiry 决定这个链接多久失效 * @param bucketName bucket名称 * @param objectName 文件名称 * @return url */ public String getObjectURL(String bucketName, String objectName) throws Exception { GetPresignedObjectUrlArgs args = GetPresignedObjectUrlArgs.builder() .bucket(bucketName) .method(Method.GET) .expiry(7, TimeUnit.DAYS) .object(objectName) .build(); return client.getPresignedObjectUrl(args); } /** * 获取文件 * * @param bucketName bucket名称 * @param objectName 文件名称 * @return 二进制流 */ public InputStream getObject(String bucketName, String objectName) throws Exception { GetObjectArgs getObjectArgs = GetObjectArgs.builder() .bucket(bucketName) .object(objectName) .build(); return client.getObject(getObjectArgs); } /** * 上传文件 base64 * @param bucketName bucket名称 * @param objectName 文件名称 * @param base64Str 文件base64 */ public String putObject(String bucketName, String objectName, String base64Str) throws Exception{ InputStream inputStream = new ByteArrayInputStream(base64Str.getBytes()); // 进行解码 BASE64Decoder base64Decoder = new BASE64Decoder(); byte[] byt = new byte[0]; try { byt = base64Decoder.decodeBuffer(inputStream); } catch (IOException e) { e.printStackTrace(); } inputStream = new ByteArrayInputStream(byt); putObject(bucketName, objectName, inputStream, Long.valueOf(byt.length)); return objectName; } /** * 上传文件 * @param bucketName bucket名称 * @param objectName 文件名称 * @param file 文件 * @throws Exception */ public String putObject( String bucketName,String objectName, MultipartFile file) throws Exception{ this.putObject(bucketName, objectName, file.getInputStream(), file.getSize()); return objectName; } /** * 获取直传链接 * @param bucketName bucket名称 * @param objectName 文件名称 * @throws Exception */ public String presignedPutObject( String bucketName,String objectName) throws Exception{ GetPresignedObjectUrlArgs getPresignedObjectUrlArgs = GetPresignedObjectUrlArgs.builder() .method(Method.PUT) .bucket(bucketName) .object(objectName) .expiry(7, TimeUnit.DAYS) .build(); return client.getPresignedObjectUrl(getPresignedObjectUrlArgs); } /** * 合并文件 * @param bucketName * @param chunkNames * @param targetObjectName * @return * @throws Exception */ public String composeObject(String bucketName, List<String> chunkNames, String targetObjectName) throws Exception{ List<ComposeSource> sources = new ArrayList<>(chunkNames.size()); for (String chunkName : chunkNames) { ComposeSource composeSource = ComposeSource.builder() .bucket(bucketName) .object(chunkName) .build(); sources.add(composeSource); } ComposeObjectArgs composeObjectArgs = ComposeObjectArgs.builder() .bucket(bucketName) .sources(sources) .object(targetObjectName) .build(); ObjectWriteResponse objectWriteResponse = client.composeObject(composeObjectArgs); return objectWriteResponse.object(); } }
Demo测试案例:-----------------------------------------------------------------
package com.smartnest.minio.demo; import com.smartnest.minio.config.MinioConfig; import com.smartnest.minio.core.MinioTemplate; import lombok.extern.slf4j.Slf4j; import java.io.File; import java.io.FileInputStream; import java.io.InputStream; @Slf4j public class DemoMinio { public static void main(String[] args) { MinioConfig config = new MinioConfig(); try { //初始化 MinioTemplate template = config.minioTemplate("http://192.168.1.188:9001","minioadmin","minioadmin",104857600); File file = new File("D:\\output\\test_file.txt"); FileInputStream in = new FileInputStream(file); //空文件上传没有意义 if(file.length()<=0) return; //上传重复文件会覆盖更新 //分区上传文件 : bucketName 桶名,objectName:文件名,文件流,文件大小 template.putObject("smart-data","test_file.txt",in,file.length()); System.out.println("IO 流文件大小 : " + in.available()); //获取文件 返回的是二进制流 InputStream downLoad = template.getObject("smart-data","paas_r.jpg"); System.out.println("获取文件的二进制流 : " + downLoad.toString()); } catch (Exception e) { e.printStackTrace(); } } }
上传成功到网页查看: