All Downloads are FREE. Search and download functionalities are using the official Maven repository.

cn.hiboot.mcn.autoconfigure.minio.DefaultMinioClient Maven / Gradle / Ivy

package cn.hiboot.mcn.autoconfigure.minio;

import cn.hiboot.mcn.core.task.TaskThreadPool;
import cn.hiboot.mcn.core.util.McnUtils;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimap;
import io.minio.*;
import io.minio.http.Method;
import io.minio.messages.Part;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;

/**
 * DefaultMinioClient
 *
 * @author DingHao
 * @since 2021/11/8 17:31
 */
public class DefaultMinioClient extends MinioAsyncClient {

    private static final Logger log = LoggerFactory.getLogger(DefaultMinioClient.class);

    private long size;

    private static final int MAX_PART = ObjectWriteArgs.MAX_MULTIPART_COUNT;

    private OkHttpClient okHttpClient;

    private TaskThreadPool pool;

    private int expire;

    private Method method;

    private MinioProperties minioProperties;

    public DefaultMinioClient(MinioProperties minioProperties,MinioAsyncClient.Builder builder) {
        this(builder.credentials(minioProperties.getAccessKey(),minioProperties.getSecretKey())
                .endpoint(minioProperties.getEndpoint())
                .httpClient(minioProperties.getClient().okHttpClient())
                .build());
        this.minioProperties = minioProperties;
        this.okHttpClient = minioProperties.getClient().okHttpClient();
        this.pool = new TaskThreadPool(minioProperties.getPool().getCore(),minioProperties.getPool().getMax(),minioProperties.getPool().getQueueSize(),minioProperties.getPool().getThreadName());
        this.size = minioProperties.getMinMultipartSize().toBytes();
        this.expire = minioProperties.getExpire();
        this.method = Method.valueOf(minioProperties.getMethod());
    }

    private DefaultMinioClient(MinioAsyncClient client) {
        super(client);
    }

    public MinioProperties getConfig() {
        return minioProperties;
    }

    public void upload(String bucketName, String objectName, long length, String contentType, InputStream inputStream) throws Exception{
        int intSize = (int)size;
        int count = (int) ((length / size) + 1);
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream(intSize);
        byte[] d = new byte[intSize];
        PreSignResult preSignResult = getPresignedObjectUrl(bucketName,objectName,contentType,count);
        int c;
        int index = 0;
        while ((c = inputStream.read(d)) != -1){
            outputStream.reset();
            outputStream.write(d,0,c);
            byte[] bytes = outputStream.toByteArray();
            String url = preSignResult.getUploadUrls().get(index++);
            pool.execute(() -> upload(url, contentType,bytes));
        }
        pool.closeUntilAllTaskFinish();
        mergeMultipartUpload(bucketName,objectName, preSignResult.getUploadId());
    }

    private void upload(String url,String contentType,byte[] data){
        try {
            okHttpClient.newCall(new Request.Builder().url(url).put(RequestBody.create(data,MediaType.parse(getOrDefault(contentType)))).build()).execute();
        } catch (IOException e) {
            log.error("async upload failed {}",e.getMessage());
        }
    }

    private String getOrDefault(String contentType){
        if(McnUtils.isNullOrEmpty(contentType)){
            contentType = "application/octet-stream";
        }
        return contentType;
    }

    public PreSignResult getPresignedObjectUrl(String bucketName,String objectName,String contentType, int count) throws Exception{
        Multimap headers = HashMultimap.create();
        headers.put("Content-Type", getOrDefault(contentType));
        PreSignResult preSignResult = new PreSignResult(count);
        if(count == 1){
            preSignResult.getUploadUrls().add(getPresignedObjectUrl(bucketName,objectName,null));
        }else {
            CreateMultipartUploadResponse response = createMultipartUploadAsync(bucketName, region, objectName, headers, null).get();
            String uploadId = response.result().uploadId();

            Map reqParams = new HashMap<>();
            reqParams.put("uploadId", uploadId);
            preSignResult.setUploadId(uploadId);
            for (int i = 1; i <= count; i++) {
                reqParams.put("partNumber", String.valueOf(i));
                preSignResult.getUploadUrls().add(getPresignedObjectUrl(bucketName,objectName,reqParams));
            }
        }
        return preSignResult;
    }

    private String getPresignedObjectUrl(String bucketName,String objectName,Map queryParams) throws Exception{
        return getPresignedObjectUrl(
                GetPresignedObjectUrlArgs.builder()
                        .method(method)
                        .bucket(bucketName)
                        .object(objectName)
                        .expiry(expire)
                        .extraQueryParams(queryParams)
                        .build());
    }

    public void mergeMultipartUpload(String bucketName,String objectName, String uploadId) throws Exception{
        Part[] parts = new Part[MAX_PART];
        ListPartsResponse partResult = listPartsAsync(bucketName, null, objectName, MAX_PART, 0, uploadId, null, null).get();
        int partNumber = 1;
        for (Part part : partResult.result().partList()) {
            parts[partNumber - 1] = new Part(partNumber, part.etag());
            partNumber++;
        }
        if(partNumber == 1){
            throw new MinioException("未找到需要合并的块");
        }
        completeMultipartUploadAsync(bucketName, region, objectName, uploadId, parts, null, null).get();
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy