[SpringBoot アプリケーション] SpringBoot は MinIO オブジェクト ストレージ サービスを統合します

オブジェクトストレージサービス MinIO

MinIO の概要

MinIO は、Apache License v2.0 オープン ソース プロトコルに基づくオブジェクト ストレージ サービスで、大量の写真、ビデオ、ドキュメントを保存するクラウド ストレージ ソリューションとして使用できます。Golang で実装されているため、サーバーは Windows、Linux、OS X、FreeBSD 上で動作できます。構成は単純で、基本的に実行可能プログラムをコピーし、1 行のコマンドで実行します。

MinIO は Amazon S3 クラウド ストレージ サービス インターフェイスと互換性があり、写真、ビデオ、ログ ファイル、バックアップ データ、コンテナ/仮想マシン イメージなどの大容量の非構造化データの保存に非常に適しており、オブジェクト ファイルはkb から最大 5T までの範囲の任意のサイズ。

S3(Simple Storage Service 簡易ストレージサービス)

基本的な考え方

  • バケット – ファイル システムに似たディレクトリ
  • オブジェクト – ファイル システムに類似したファイル
  • キー – アナログファイル名

公式 Web サイトのドキュメント: http://docs.minio.org.cn/docs/

MinIO の機能

一般的なクラウド ストレージの例には、Qiniu Cloud、Alibaba Cloud などが含まれます。デメリットはお金がかかること

プライベートストレージシステム: fastdfs (インストールとデプロイメントが非常に面倒、hadoop をインストールする必要がある、インターフェースがない)、mongodb に付属する GridFS (使用上のデメリットも多い) ため、MinIO と比較すると、次のような利点があります。以下に続きます:

  • SDKのサポート

    MinIO は、高性能分散ストレージ ソリューションを開発するための Golang プログラミング言語に基づくオープンソース プロジェクトであり、Minio の軽量な特性に基づいて、Java、Python、Go などの言語の SDK によってサポートされており、非常に完全な公式ウェブサイトのドキュメントがあります。

  • 簡単なインストールと展開

    Linux 環境では、バイナリ ファイルをダウンロードして実行するだけで、MinIO のインストールと構成が数分で完了します。構成オプションとバリエーションの数は最小限に抑えられるため、構成が失敗する可能性はほぼゼロに減少します。MinIO のアップグレードは簡単なコマンドで完了し、このコマンドにより MinIO のアップグレード作業を中断することなく完了でき、ダウンタイムなしでアップグレード操作を完了できるため、総使用量と運用保守コストが大幅に削減されます。

  • 操作ページあり

    MinIO サービスをインストールすると、ブラウザから直接システムにログインでき、ユーザーフレンドリーなシンプルな操作インターフェイスにより、バケットとその中のファイル リソースの管理が非常に便利になります。

  • データ保護

    Minio は、ハードウェア障害を防ぐために Minio Erasure Code を使用します。ドライバーの半分以上が破損した場合でも、回復することができます。

  • ハイパフォーマンス

    高性能オブジェクト ストレージとして、標準的なハードウェア条件下で 55GB/s の読み取り速度と 35GB/s の書き込み速度を達成できます。

  • 拡張可能

    異なる MinIO クラスターはフェデレーションを形成し、複数のデータセンターにまたがるグローバル名前空間を形成できます。

  • シンプルな機能

    この設計原則により、MinIO はエラーが発生しにくくなり、起動が速くなります。

  • 豊富なAPI

    ファイルリソース共有リンクと共有リンクの有効期限ポリシー、バケット操作、ファイルリストへのアクセス、ファイルのアップロードとダウンロードなどの基本機能をサポートします。

  • ファイル変更のプロアクティブな通知

    オブジェクトのアップロードやオブジェクトの削除など、バケット (Bucket) が変更された場合は、バケット イベント通知メカニズムを使用して、AMQP、MQTT、Elasticsearch、Redis、NATS、MySQL、Kafka、Webhook、等

箱から出してそのまま使用

Dockerのインストールが始まります

環境の展開と起動には最新の docker を使用できます2023-08-31T15-31-16Z

docker run -p 9000:9000 -p 9090:9090 --name minio -d --restart=always -e "MINIO_ACCESS_KEY=minio" -e "MINIO_SECRET_KEY=minio123" -v /home/data:/data -v /home/config:/root/.minio minio/minio server /data --console-address ":9090" -address ":9000"

ここに画像の説明を挿入します

管理コンソール

サーバー アドレスが であると仮定し192.168.171.128、アドレス バーに http://192.168.171.128:9000/ と入力して、ログイン インターフェイスに入ります。

ここに画像の説明を挿入します

アクセスキーはDocker コンテナ作成時に作成されるminioSecret_keyminio123で、システムに入るとメインインターフェイスが表示されます。

ここに画像の説明を挿入します

バケットを作成するには、「バケットの作成」をクリックします。ここでのバケットは、ファイルが保存されるディレクトリとして理解できます。複数のバケットは、互いに独立して作成できます。

ここに画像の説明を挿入します

クイックスタート

Java がファイルを minio にアップロードする

pom 依存関係

<dependencies>
    <dependency>
        <groupId>io.minio</groupId>
        <artifactId>minio</artifactId>
        <version>7.1.0</version>
    </dependency> 
</dependencies>

テストクラスを作成してファイルをアップロードする

public class MinIOTest {
    
    


     public static void main(String[] args) {
    
    

        FileInputStream fileInputStream = null;
        try {
    
    

            fileInputStream =  new FileInputStream("D:\\study\\images\\1.png");;

            //1.创建minio链接客户端
            MinioClient minioClient = MinioClient.builder().credentials("minio", "minio123").endpoint("http://192.168.171.128:9000").build();
            //2.上传
            String objectName = UUID.randomUUID().toString();
            PutObjectArgs putObjectArgs = PutObjectArgs.builder()
                    .object(objectName+".png")//文件名
                    .contentType("image/jpg")//文件类型 MediaType.IMAGE_PNG_VALUE代替
                    .bucket("miniotest")//桶名词  与minio创建的名词一致
                    .stream(fileInputStream, fileInputStream.available(), -1) //文件流
                    .build();
            minioClient.putObject(putObjectArgs);

            System.out.println("http://192.168.171.128:9000/miniotest/"+objectName+".png");

        } catch (Exception ex) {
    
    
            ex.printStackTrace();
        }
    }
}

オブジェクト名として UUID を使用します。

  • オブジェクト名の競合を避けるための一意性。

  • 実際のファイル情報を非表示にし、プライバシーを向上させます。

  • オブジェクト名は、元のファイル名の長さや特殊文字によって制限されません。

実際のシナリオでは、ファイルの識別と管理にさらに注意を払う場合は、ファイル名の使用を検討できます。一意性とプライバシーにさらに注意を払う場合は、UUID の使用を検討してください。
同時に、ファイル名をオブジェクト プロパティとして保存し、UUID をオブジェクト名として使用するなど、2 つを組み合わせることもできます。これにより、ファイル情報が保存され、一意性が保証されます。

ここに画像の説明を挿入します

クライアント コンソールにアクセスすると、イメージが正常にアップロードされています。

ここに画像の説明を挿入します

アクセス許可を構成する

アップロードしたファイルにブラウザでアクセスします アクセスするファイル形式はhttp://minio服务器ip:9090/存储桶/文件名こちらですhttp://192.168.171.128:9000/miniotest/dc7a7378-eb4e-4622-afd6-32f3b41e14bf.pngアクセスするとエラーになります作成したバケットスペースの設定がプライベートであり、他のユーザーにアクセス権限がないためです

ここに画像の説明を挿入します

ここに画像の説明を挿入します

アップロードしたファイルに匿名ユーザーがアクセスできるようにする必要がある場合は、アクセス許可をPublic権限に変更する必要があります。

ここに画像の説明を挿入します

ブラウザアクセス成功

ここに画像の説明を挿入します

MinIO をスターターとしてカプセル化する

モジュール zy-minio-starter を作成する

依存関係をインポートする

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-autoconfigure</artifactId>
    </dependency>
    <dependency>
        <groupId>io.minio</groupId>
        <artifactId>minio</artifactId>
        <version>7.1.0</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-configuration-processor</artifactId>
        <optional>true</optional>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>
</dependencies>

構成クラス

MinIOConfigProperties

@Data
@ConfigurationProperties(prefix = "minio")  // 文件上传 配置前缀file.oss
public class MinIOConfigProperties implements Serializable {
    
    

    private String accessKey;
    private String secretKey;
    private String bucket;
    private String endpoint;
    private String readPath;
}

MinIOConfig

@Configuration
@EnableConfigurationProperties({
    
    MinIOConfigProperties.class})
//当引入FileStorageService接口时
@ConditionalOnClass(FileStorageService.class)
public class MinIOConfig {
    
    

   @Autowired
   private MinIOConfigProperties minIOConfigProperties;

    @Bean
    public MinioClient buildMinioClient(){
    
    
        return MinioClient
                .builder()
                .credentials(minIOConfigProperties.getAccessKey(), minIOConfigProperties.getSecretKey())
                .endpoint(minIOConfigProperties.getEndpoint())
                .build();
    }
}

カプセル化操作 minIO クラス

ファイルストレージサービス

public interface FileStorageService {
    
    


    /**
     *  上传图片文件
     * @param prefix  文件前缀
     * @param filename  文件名
     * @param inputStream 文件流
     * @return  文件全路径
     */
    public String uploadImgFile(String prefix, String filename,InputStream inputStream);

    /**
     *  上传html文件
     * @param prefix  文件前缀
     * @param filename   文件名
     * @param inputStream  文件流
     * @return  文件全路径
     */
    public String uploadHtmlFile(String prefix, String filename,InputStream inputStream);

    /**
     * 删除文件
     * @param pathUrl  文件全路径
     */
    public void delete(String pathUrl);

    /**
     * 下载文件
     * @param pathUrl  文件全路径
     * @return
     *
     */
    public byte[]  downLoadFile(String pathUrl);

}

MinIOFileStorageService

@Slf4j
@Import(MinIOConfig.class)
public class MinIOFileStorageService implements FileStorageService {
    
    

    @Autowired
    private MinioClient minioClient;

    @Autowired
    private MinIOConfigProperties minIOConfigProperties;

    private final static String separator = "/";

    /**
     * @param dirPath
     * @param filename  yyyy/mm/dd/file.jpg
     * @return
     */
    public String builderFilePath(String dirPath,String filename) {
    
    
        StringBuilder stringBuilder = new StringBuilder(50);
        if(!StringUtils.isEmpty(dirPath)){
    
    
            stringBuilder.append(dirPath).append(separator);
        }
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd");
        String todayStr = sdf.format(new Date());
        stringBuilder.append(todayStr).append(separator);
        stringBuilder.append(filename);
        return stringBuilder.toString();
    }

    /**
     *  上传图片文件
     * @param prefix  文件前缀
     * @param filename  文件名
     * @param inputStream 文件流
     * @return  文件全路径
     */
    @Override
    public String uploadImgFile(String prefix, String filename,InputStream inputStream) {
    
    
        String filePath = builderFilePath(prefix, filename);
        try {
    
    
            PutObjectArgs putObjectArgs = PutObjectArgs.builder()
                    .object(filePath)
                    .contentType("image/jpg")
                    .bucket(minIOConfigProperties.getBucket()).stream(inputStream,inputStream.available(),-1)
                    .build();
            minioClient.putObject(putObjectArgs);
            StringBuilder urlPath = new StringBuilder(minIOConfigProperties.getReadPath());
            urlPath.append(separator+minIOConfigProperties.getBucket());
            urlPath.append(separator);
            urlPath.append(filePath);
            return urlPath.toString();
        }catch (Exception ex){
    
    
            log.error("minio put file error.",ex);
            throw new RuntimeException("上传文件失败");
        }
    }

    /**
     *  上传html文件
     * @param prefix  文件前缀
     * @param filename   文件名
     * @param inputStream  文件流
     * @return  文件全路径
     */
    @Override
    public String uploadHtmlFile(String prefix, String filename,InputStream inputStream) {
    
    
        String filePath = builderFilePath(prefix, filename);
        try {
    
    
            PutObjectArgs putObjectArgs = PutObjectArgs.builder()
                    .object(filePath)
                    .contentType("text/html")
                    .bucket(minIOConfigProperties.getBucket()).stream(inputStream,inputStream.available(),-1)
                    .build();
            minioClient.putObject(putObjectArgs);
            StringBuilder urlPath = new StringBuilder(minIOConfigProperties.getReadPath());
            urlPath.append(separator+minIOConfigProperties.getBucket());
            urlPath.append(separator);
            urlPath.append(filePath);
            return urlPath.toString();
        }catch (Exception ex){
    
    
            log.error("minio put file error.",ex);
            ex.printStackTrace();
            throw new RuntimeException("上传文件失败");
        }
    }

    /**
     * 删除文件
     * @param pathUrl  文件全路径
     */
    @Override
    public void delete(String pathUrl) {
    
    
        String key = pathUrl.replace(minIOConfigProperties.getEndpoint()+"/","");
        int index = key.indexOf(separator);
        String bucket = key.substring(0,index);
        String filePath = key.substring(index+1);
        // 删除Objects
        RemoveObjectArgs removeObjectArgs = RemoveObjectArgs.builder().bucket(bucket).object(filePath).build();
        try {
    
    
            minioClient.removeObject(removeObjectArgs);
        } catch (Exception e) {
    
    
            log.error("minio remove file error.  pathUrl:{}",pathUrl);
            e.printStackTrace();
        }
    }


    /**
     * 下载文件
     * @param pathUrl  文件全路径
     * @return  文件流
     *
     */
    @Override
    public byte[] downLoadFile(String pathUrl)  {
    
    
        String key = pathUrl.replace(minIOConfigProperties.getEndpoint()+"/","");
        int index = key.indexOf(separator);
        String bucket = key.substring(0,index);
        String filePath = key.substring(index+1);
        InputStream inputStream = null;
        try {
    
    
            inputStream = minioClient.getObject(GetObjectArgs.builder().bucket(minIOConfigProperties.getBucket()).object(filePath).build());
        } catch (Exception e) {
    
    
            log.error("minio down file error.  pathUrl:{}",pathUrl);
            e.printStackTrace();
        }

        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        byte[] buff = new byte[100];
        int rc = 0;
        while (true) {
    
    
            try {
    
    
                if (!((rc = inputStream.read(buff, 0, 100)) > 0)) break;
            } catch (IOException e) {
    
    
                e.printStackTrace();
            }
            byteArrayOutputStream.write(buff, 0, rc);
        }
        return byteArrayOutputStream.toByteArray();
    }
}

自動構成を外部から参加する

リソースに新規作成META-INF/spring.factories

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
 cn.zysheep.file.service.impl.MinIOFileStorageService

他のマイクロサービスによる使用

まず、zy-minio-starter の依存関係をインポートします。

次に、minio に必要な構成をマイクロサービスに追加します。

minio:
  accessKey: minio
  secretKey: minio123
  bucket: miniotest
  endpoint: http://192.168.171.128:9000
  readPath: http://192.168.171.128:9000

3 番目に、対応するビジネス クラスに FileStorageService を挿入します。例は次のとおりです。

@SpringBootTest(classes = MinIOApplication.class)
public class MinioBootTest {
    
    

    @Autowired
    private FileStorageService fileStorageService;

    @Test
    public void testUpdateImgFile() {
    
    
        try {
    
    
            FileInputStream fileInputStream = new FileInputStream("D:\\study\\images\\docker3.png");
            String fileName = UUID.randomUUID().toString();
            String filePath = fileStorageService.uploadImgFile("", fileName+".jpg", fileInputStream);
            System.out.println(filePath);
        } catch (FileNotFoundException e) {
    
    
            e.printStackTrace();
        }
    }
}

インストール中に発生した問題

質問 1

ここに画像の説明を挿入します

おすすめ

転載: blog.csdn.net/qq_45297578/article/details/132670608