Vue 3.0とViteを使用したMinIOファイルアップロードシステムの実装

MinIOは高性能でS3互換のオブジェクトストレージソリューションです。大規模なAI/ML、データレイク、データベースのワークロード向けに設計されており、ソフトウェア定義ストレージです。専用ハードウェアを購入することなく、クラウドや一般的なハードウェア上で分散オブジェクトストレージを利用できます。MinIOはオープンソースのGNU AGPL v3ライセンスと商用エンタープライズライセンスのデュアルライセンスを採用しています

MinIOラッパーライブラリのインストール
npm install minio-vite-uploader
minio.jsファイルの作成と機能のカプセル化
import { fetchMinioCredentials } from "@/api/storage.js";
import { initializeMinioClient, convertFileToStream } from "minio-vite-uploader";

let storageClient = {};
let connectionConfig = {
  accessKey: "",
  secretKey: "",
  sessionToken: "",
  expiration: null,
  isExpired: null,
};

/**
 * MinIO認証情報の取得
 */
const fetchConnectionDetails = () => {
  return new Promise((resolve) => {
    fetchMinioCredentials().then((response) => {
      const { status, result } = response;
      if (status) {
        // MinIO接続情報の設定
        connectionConfig = { ...result };
        // サーバーから返されたMinIO接続情報
        // {
        //    "accessKey": "string",
        //    "expiration": {},
        //    "isExpired": true,
        //    "secretKey": "string",
        //    "sessionToken": "string"
        // }
        resolve();
      }
    });
  });
};

// ファイルアップロード機能
export async function uploadDocument(params) {
  // MinIO認証情報がない場合
  if (!connectionConfig.accessKey) {
    // 認証情報の取得
    await fetchConnectionDetails();
  }

  // MinIOクライアントオブジェクトが存在しない場合
  if (!storageClient?.accessKey) {
    storageClient = initializeMinioClient({
      endPoint: "storage.example.com", // サーバーアドレス (http不要)
      port: 9000, // ポート番号
      useSSL: false, // SSLの有効化(バックエンドのMinIO設定に依存)
      accessKey: connectionConfig.accessKey,
      secretKey: connectionConfig.secretKey,
      sessionToken: connectionConfig.sessionToken,
    });
  }

  const { document } = params;
  const storageBucket = "project_assets"; // バケット名(バックエンドから提供)
  const fileIdentifier = `${Date.now()}-${document.name}`; // 一意のファイル名
  
  // ファイルオブジェクトをストリームに変換
  convertFileToStream(document, (streamData) => {
    // バッファデータの取得
    let fileBuffer = streamData._readableState.buffer.head.data;
    // MinIOを使用したファイルアップロード
    storageClient.uploadFile(storageBucket, fileIdentifier, fileBuffer, document.size);
  });
  
  // ファイル識別子を返す(例: 1712924477054-%E6%B5%8B%E8%AF%95.jpeg)
  return fileIdentifier;
}
封装されたメソッドの使用例
<template>
  <el-upload
    class="media-uploader"
    action="#"
    v-model:file-list="uploadedFiles"
    :auto-upload="false"
    :show-file-list="false"
    :on-change="handleFileChange"
  >
    <img v-if="mediaUrl" :src="mediaUrl" class="preview-image" />

    <!-- アップロードボックス -->
    <div v-else class="upload-trigger">
      <svg-icon icon-class="icon-media-add" class-name="upload-icon" />
      <div class="instruction-text">ファイルを選択</div>
    </div>
  </el-upload>
</template>

<script setup name="MediaUploader">
import { uploadDocument } from "@/utils/storage.js";

// アップロードされたファイルリスト
const uploadedFiles = ref();
// プレビュー用URL
const mediaUrl = ref("");

/**
 * ファイル変更時の処理
 */
const handleFileChange = (file) => {
  uploadDocument({ document: file.raw }).then((identifier) => {
    // プレビューURLの設定
    mediaUrl.value = identifier;
  });
};
</script>

<style lang="scss" scoped>
.media-uploader {
  .preview-image {
    width: 100%;
    height: 100%;
    object-fit: cover;
  }
  
  .upload-trigger {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    border: 2px dashed #d9d9d9;
    border-radius: 6px;
    cursor: pointer;
    
    .upload-icon {
      font-size: 28px;
      color: #999;
      margin-bottom: 8px;
    }
    
    .instruction-text {
      color: #666;
      font-size: 14px;
    }
  }
}
</style>
実装結果

上記のコードを実装することで、Vue 3.0とViteを使用したMinIOファイルアップロードシステムが完成します。ユーザーはインターフェースをクリックしてファイルを選択し、選択されたファイルが自動的にMinIOストレージにアップロードされます。アップロード後、ファイルの識別子が返され、それを使用してファイルにアクセスできます。

この実装は、大規模なファイルストレージ要件を持つアプリケーションに適しています。MinIOのS3互換性により、AWS S3と同様のAPIを使用してファイルを管理できます。また、認証情報は動的に取得されるため、セキュリティも確保されています。

タグ: vue.js Vite minio ファイルアップロード オブジェクトストレージ

6月18日 20:14 投稿