MinIO上傳和下載檔案及檔案完整性校驗.

CoderManolin發表於2024-10-25

MinIO上傳和下載檔案及檔案完整性校驗.

package com.xuecheng.media;

import com.j256.simplemagic.ContentInfo;
import com.j256.simplemagic.ContentInfoUtil;
import io.minio.*;
import io.minio.errors.*;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.io.IOUtils;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.MediaType;

import java.io.*;
import java.util.HashMap;
import java.util.Map;

/**
 * 測試minio的sdk
 *
 * @author ManolinCoder
 * @date 2024-10-21
 */


@SpringBootTest
public class MinioTest {


    // MinIO伺服器地址
    String url = "http://localhost:9000";
    // MinIO訪問金鑰
    String accessKey = "accessKey";
    // MinIO秘密金鑰
    String secretKey = "secretKey";

    // 待上傳的檔案路徑
    String filePath = "/Users/lcm/Movies/測試影片/1.mp4";
    // MinIO儲存桶名稱
    String bucketName = "testbucket";
    // 儲存桶中的物件名稱
    String objectName = "1.mp4";


    MinioClient minioClient = MinioClient.builder().endpoint(url).credentials(accessKey, secretKey).build();


    /**
     * 上傳檔案
     *
     * @param
     * @return void
     * @author ManolinCoder
     * @date 2024-10-21
     */
    @Test
    public void testUpload() throws Exception {

        ContentInfo extensionMatch = ContentInfoUtil.findExtensionMatch(".mp4");
        String mimeType = MediaType.APPLICATION_OCTET_STREAM_VALUE;  // 通用 mimeType 位元組流


        if (extensionMatch != null) {
            mimeType = extensionMatch.getMimeType();
        }

        try {

            // Make 'asiatrip' bucket if not exist.
            boolean found = minioClient.bucketExists(BucketExistsArgs.builder().bucket("testbucket").build());
            if (!found) {
                // Make a new bucket called 'asiatrip'.
                minioClient.makeBucket(MakeBucketArgs.builder().bucket("testbucket").build());
            } else {
                System.out.println("檔案桶已存在!!!");
            }

            // 上傳檔案
            uploadFile(minioClient, filePath, bucketName, objectName, mimeType);

            //上傳檔案完整性校驗
            boolean flag = checkFileIntegrity(minioClient, filePath, bucketName, objectName);


            System.out.println(flag ? "上傳檔案成功了!!!" : "上傳檔案失敗了!!!");


        } catch (MinioException e) {
            System.out.println("Error occurred: " + e);
            System.out.println("HTTP trace: " + e.httpTrace());
        }


    }


    /**
     * 刪除檔案
     *
     * @param
     * @return void
     * @author ManolinCoder
     * @date 2024-10-21
     */
    @Test
    public void testDelete() throws Exception {

        RemoveObjectArgs removeObjectArgs = RemoveObjectArgs.builder().bucket("testbucket").object("1.MP4").build();

        minioClient.removeObject(removeObjectArgs);


    }


    /**
     * 查詢檔案,下載到本地
     *
     * @param
     * @return void
     * @author ManolinCoder
     * @date 2024-10-21
     */
    @Test
    public void testGetObject() throws Exception {

        GetObjectArgs getObjectArgs = GetObjectArgs.builder().bucket("testbucket").object("1.MP4").build();

        FilterInputStream inputStream = minioClient.getObject(getObjectArgs);

        String localFileName = "/Users/lcm/Downloads/1.mp4";

        // 指定輸出流
        FileOutputStream outputStream = new FileOutputStream(new File(localFileName));
        IOUtils.copy(inputStream, outputStream);

        // md5完整性校驗
        boolean flag = checkFileIntegrity(minioClient, localFileName, bucketName, objectName);


        if (flag) {
            System.out.println("下載成功了!!!");
        } else {
            System.out.println("下載失敗了!!!");
        }


    }


    /**
     * 上傳檔案
     *
     * @param minioClient
     * @param filePath
     * @param bucketName
     * @param objectName
     * @param contentType
     * @return void
     * @author CoderManolin
     * @date 2024-10-25
     */
    public void uploadFile(MinioClient minioClient, String filePath, String bucketName, String objectName, String contentType) throws Exception {

        // 計算上傳前本地檔案MD5
        String uploadLocalFileMD5 = calculateMD5(filePath);
        System.out.println("上傳前本地檔案MD5: uploadLocalFileMD5=" + uploadLocalFileMD5);
        Map<String, String> md5Map = new HashMap<>();
        md5Map.put("md5", uploadLocalFileMD5);


        //上傳檔案到 MinIO
        File file = new File(filePath);
        minioClient.putObject(
                PutObjectArgs.builder()
                        .bucket(bucketName)
                        .object(objectName)
                        .stream(new FileInputStream(file), file.length(), -1)
                        .userMetadata(md5Map)
                        .contentType(contentType)
                        .build()
        );
        System.out.println("File uploaded successfully: " + objectName);

    }


    /**
     * 計算md5
     *
     * @param filePath
     * @return File
     * @author ManolinCoder
     * @date 2024-10-23
     */
    public String calculateMD5(String filePath) throws Exception {
        FileInputStream fileInputStream = new FileInputStream(filePath);
        return DigestUtils.md5Hex(fileInputStream);
    }


    /**
     * 對比本地檔案和minio檔案的MD5值是否一致,校驗檔案完整性
     *
     * @param minioClient
     * @param filePath
     * @param bucketName
     * @param objectName
     * @return boolean
     * @author CoderManolin
     * @date 2024-10-25
     */

    public boolean checkFileIntegrity(MinioClient minioClient, String filePath, String bucketName, String objectName) throws Exception {


        // 計算本地檔案的MD5
        String localFileMD5 = calculateMD5(filePath);
        System.out.println("Local file MD5: " + localFileMD5);

        // 獲取MinIO中物件的MD5
        StatObjectResponse stat = minioClient.statObject(
                StatObjectArgs.builder()
                        .bucket(bucketName)
                        .object(objectName)
                        .build());

        String minioFileMD5 = stat.userMetadata().get("md5");
        System.out.println("MinIO file MD5: " + minioFileMD5);

        // 比較MD5值
        return localFileMD5.equals(minioFileMD5);


    }

}

相關文章