minio下載地址:https://dl.min.io/

mc在MinIO中創建用户創建policy用户和policy的綁定(minio)_上傳

有2個程序,一個minio,一個 mc 是(minio client)簡稱。

wget https://dl.min.io/community/server/minio/release/linux-amd64/minio
wget https://dl.min.io/community/client/mc/release/linux-amd64/mc


一、minio程序

minio服務

minio server /miniodata --console-address :9001
minio server /miniodata --console-address ":9001" 
minio server /miniodata --console-address ":9001" >/dev/null 2>&1 &
MINIO_ROOT_USER=admin MINIO_ROOT_PASSWORD=password minio server /usr/local/miniodata --console-address ":9001" 


nohup minio server /miniodata --console-address :9001 >/dev/null 2>&1 & 
nohup ./minio server /miniodata --console-address :9001 >/dev/null 2>&1 &



二、mc程序

(一):mc管理minio的端點,桶,用户,策略

mc管理minio的Endpoint端點

mc alias list
mc alias set 'myminio' 'http://192.168.202.240:9000' 'minioadmin' 'minioadmin'
mc alias remove myminio
另外還有import和export感覺不常用

mc在MinIO中創建用户創建policy用户和policy的綁定(minio)_顯示文件_02

./mc alias set 'myminio' 'http://192.168.202.240:9000' 'minioadmin' 'minioadmin'

mc在MinIO中創建用户創建policy用户和policy的綁定(minio)_顯示文件_03

mc管理Buckets桶(以myminio端點為例)

mc mb myminio/mybucket
mc mb myminio/mybuckettest
mc rb myminio/mybuckettest

mc在MinIO中創建用户創建policy用户和policy的綁定(minio)_基本語法_04

mc管理user用户(以myminio端點為例)

# 創建新用户,好像修改用户密碼也是用它
mc admin user add myminio username password
# 示例:創建一個名為 testuser 的用户
mc admin user add myminio testuser TestPassword123!
# 查看用户的信息
mc admin user info myminio testuser

mc在MinIO中創建用户創建policy用户和policy的綁定(minio)_顯示文件_05

mc在MinIO中創建用户創建policy用户和policy的綁定(minio)_基本語法_06

mc管理policy策略(以myminio端點為例)

# 查看某個端點的所有的policy,會有一些系統默認的策略
mc admin policy list myminio

mc在MinIO中創建用户創建policy用户和policy的綁定(minio)_基本語法_07

# 方法1:創建策略文件然後添加
cat > limited-bucket-policy.json << EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "s3:GetObject",
        "s3:PutObject",
        "s3:DeleteObject",
        "s3:ListBucket"
      ],
      "Resource": [
        "arn:aws:s3:::allowed-bucket1/*",
        "arn:aws:s3:::allowed-bucket1",
        "arn:aws:s3:::allowed-bucket2/*",
        "arn:aws:s3:::allowed-bucket2"
      ]
    }
  ]
}
EOF

# 添加策略到MinIO
mc admin policy create myminio limited-bucket-policy limited-bucket-policy.json

mc admin policy create TARGET POLICYNAME POLICYFILE
# 將策略分配給用户
mc admin policy attach myminio limited-bucket-policy --user testuser

mc進行用户和策略的綁定(以myminio端點為例)

# 將策略分配給用户
mc admin policy attach myminio limited-bucket-policy --user testuser

一個完整的策略應該案例

# 1. 創建用户
mc admin user add myminio testuser TestPassword123!

# 2. 創建策略文件
cat > testuser-policy.json << EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "s3:GetObject",
        "s3:PutObject",
        "s3:DeleteObject",
        "s3:ListBucket",
        "s3:GetBucketLocation"
      ],
      "Resource": [
        "arn:aws:s3:::bucket1/*",
        "arn:aws:s3:::bucket1",
        "arn:aws:s3:::bucket2/*",
        "arn:aws:s3:::bucket2"
      ]
    }
  ]
}
EOF

# 3. 添加策略
mc admin policy add myminio testuser-policy testuser-policy.json

# 4. 分配策略給用户
mc admin policy set myminio testuser-policy user=testuser

# 5. 驗證用户
mc admin user list myminio

# 6. 測試用户權限
mc alias set testuser-alias http://localhost:9000 testuser TestPassword123!
mc ls testuser-alias

一些常用的策略模板

模板1:單個bucket完全訪問
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": ["s3:*"],
      "Resource": [
        "arn:aws:s3:::my-bucket/*",
        "arn:aws:s3:::my-bucket"
      ]
    }
  ]
}
模板2:多個bucket只讀訪問
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "s3:GetObject",
        "s3:ListBucket"
      ],
      "Resource": [
        "arn:aws:s3:::bucket1/*",
        "arn:aws:s3:::bucket1",
        "arn:aws:s3:::bucket2/*",
        "arn:aws:s3:::bucket2"
      ]
    }
  ]
}
模板3:特定路徑訪問
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "s3:GetObject",
        "s3:PutObject",
        "s3:DeleteObject"
      ],
      "Resource": [
        "arn:aws:s3:::my-bucket/user-folder/*"
      ]
    },
    {
      "Effect": "Allow",
      "Action": ["s3:ListBucket"],
      "Resource": ["arn:aws:s3:::my-bucket"],
      "Condition": {
        "StringLike": {
          "s3:prefix": ["user-folder/*"]
        }
      }
    }
  ]
}

真實完整的策略應用案例

mc在MinIO中創建用户創建policy用户和policy的綁定(minio)_顯示文件_08

a.json

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": ["s3:*"],
      "Resource": [
        "arn:aws:s3:::hardnetwork/*",
        "arn:aws:s3:::hardnetwork",
        "arn:aws:s3:::rpa/*",
        "arn:aws:s3:::rpa",
        "arn:aws:s3:::databases/*",
        "arn:aws:s3:::databases",
        "arn:aws:s3:::product/*",
        "arn:aws:s3:::product",
        "arn:aws:s3:::dev/*",
        "arn:aws:s3:::dev",
        "arn:aws:s3:::tools/*",
        "arn:aws:s3:::tools"
      ]
    }
  ]
}
# 創建策略文件a.json,並根據策略文件創建名為xinxibu-policy的策略
./mc admin policy create myminio xinxibu-policy a.json
# 查看myminio端點的策略,多了一個名為xinxibu-policy的策略
./mc admin policy list myminio
# 在myminio端點創建賬號和密碼
./mc admin user add myminio wumingcan wumingcan123!
# 在指定的myminio端點進行策略和用户的綁定
./mc admin policy attach myminio xinxibu-policy --user wumingcan

mc在MinIO中創建用户創建policy用户和policy的綁定(minio)_顯示文件_09

mc在MinIO中創建用户創建policy用户和policy的綁定(minio)_上傳_10



(二):mc管理minio存儲的對象操作

put - 上傳文件/對象

# 基本語法
mc put [FLAGS] FILE... TARGET

# 上傳單個文件
mc put /path/to/local/file.txt myminio/mybucket/

# 上傳文件並重命名
mc put /path/to/local/file.txt myminio/mybucket/new-name.txt

# 上傳多個文件
mc put /path/to/local/*.jpg myminio/mybucket/images/

# 上傳時設置存儲類別
mc put --storage-class REDUCED_REDUNDANCY /path/to/file.txt myminio/mybucket/

# 上傳時設置元數據
mc put --attr "Content-Type=application/pdf" /path/to/doc.pdf myminio/mybucket/

# 上傳時設置標籤
mc put --tags "env=prod,type=backup" /path/to/file.txt myminio/mybucket/

# 顯示上傳進度
mc put --progress /path/to/large-file.zip myminio/mybucket/

# 禁用多部分上傳
mc put --disable-multipart /path/to/file.txt myminio/mybucket/

# 設置多部分上傳的塊大小
mc put --part-size 64MB /path/to/large-file.zip myminio/mybucket/

# 上傳時加密
mc put --encrypt-key "myminio/mybucket/=32byteslongsecretkeymustbegiven1" /path/to/file.txt myminio/mybucket/

# 從標準輸入上傳
echo "Hello World" | mc put - myminio/mybucket/hello.txt

# 上傳並設置過期時間
mc put --expire 7d /path/to/temp-file.txt myminio/mybucket/temp/

get - 下載文件/對象

# 基本語法
mc get [FLAGS] SOURCE TARGET

# 下載單個文件
mc get myminio/mybucket/file.txt /path/to/local/

# 下載文件並重命名
mc get myminio/mybucket/file.txt /path/to/local/new-name.txt

# 下載多個文件
mc get myminio/mybucket/images/*.jpg /path/to/local/images/

# 遞歸下載整個目錄
mc get --recursive myminio/mybucket/directory/ /path/to/local/

# 顯示下載進度
mc get --progress myminio/mybucket/large-file.zip /path/to/local/

# 斷點續傳下載
mc get --continue myminio/mybucket/large-file.zip /path/to/local/

# 下載到標準輸出
mc get myminio/mybucket/file.txt -

# 下載時解密
mc get --encrypt-key "myminio/mybucket/=32byteslongsecretkeymustbegiven1" myminio/mybucket/encrypted-file.txt /path/to/local/

# 下載特定版本
mc get --version-id "version-id-here" myminio/mybucket/file.txt /path/to/local/

# 保留文件屬性
mc get --preserve myminio/mybucket/file.txt /path/to/local/

# 驗證校驗和
mc get --checksum myminio/mybucket/file.txt /path/to/local/

rm - 刪除文件/對象(詳細版本)

# 基本語法
mc rm [FLAGS] TARGET...

# 刪除單個文件
mc rm myminio/mybucket/file.txt

# 刪除多個文件
mc rm myminio/mybucket/file1.txt myminio/mybucket/file2.txt

# 遞歸刪除目錄
mc rm --recursive myminio/mybucket/directory/

# 強制刪除(不提示確認)
mc rm --force myminio/mybucket/file.txt

# 刪除匹配模式的文件
mc rm myminio/mybucket/*.tmp

# 刪除指定時間之前的文件
mc rm --recursive --older-than 30d myminio/mybucket/logs/

# 刪除指定時間之後的文件
mc rm --recursive --newer-than 2023-01-01 myminio/mybucket/temp/

# 模擬刪除(顯示要刪除的文件但不實際刪除)
mc rm --dry-run --recursive myminio/mybucket/old-data/

# 刪除不完整的多部分上傳
mc rm --incomplete myminio/mybucket/

# 刪除所有版本(版本控制環境)
mc rm --recursive --versions myminio/mybucket/file.txt

# 刪除特定版本
mc rm --version-id "version-id-here" myminio/mybucket/file.txt

# 刪除時忽略錯誤
mc rm --force --recursive --ignore-errors myminio/mybucket/problematic-directory/

# 刪除標籤匹配的文件
mc rm --recursive --tags "env=test" myminio/mybucket/

# 批量刪除(從文件列表)
cat file-list.txt | xargs -I {} mc rm myminio/mybucket/{}

cp - 複製文件/對象

# 基本語法
mc cp [FLAGS] SOURCE TARGET

# 從本地複製文件到MinIO
mc cp /path/to/local/file.txt myminio/mybucket/

# 從本地複製整個目錄到MinIO
mc cp --recursive /path/to/local/directory/ myminio/mybucket/remote-directory/

# 從MinIO下載文件到本地
mc cp myminio/mybucket/file.txt /path/to/local/

# 從MinIO下載整個目錄到本地
mc cp --recursive myminio/mybucket/directory/ /path/to/local/

# 在MinIO內部複製(bucket之間)
mc cp myminio/source-bucket/file.txt myminio/target-bucket/

# 複製時重命名
mc cp myminio/mybucket/old-name.txt myminio/mybucket/new-name.txt

# 批量複製(使用通配符)
mc cp myminio/mybucket/*.jpg /path/to/local/images/

# 顯示進度條
mc cp --progress /large-file.zip myminio/mybucket/

# 保持文件屬性
mc cp --preserve myminio/mybucket/file.txt /path/to/local/

# 排除特定文件
mc cp --recursive --exclude "*.tmp" /path/to/source/ myminio/mybucket/

# 包含特定文件
mc cp --recursive --include "*.pdf" /path/to/source/ myminio/mybucket/

# 覆蓋已存在的文件
mc cp --overwrite /path/to/file.txt myminio/mybucket/

mv - 移動/重命名文件

# 基本語法
mc mv [FLAGS] SOURCE TARGET

# 移動本地文件到MinIO
mc mv /path/to/local/file.txt myminio/mybucket/

# 從MinIO移動文件到本地
mc mv myminio/mybucket/file.txt /path/to/local/

# 在MinIO內重命名文件
mc mv myminio/mybucket/old-name.txt myminio/mybucket/new-name.txt

# 移動整個目錄
mc mv --recursive myminio/mybucket/old-directory/ myminio/mybucket/new-directory/

# 在不同bucket間移動
mc mv myminio/source-bucket/file.txt myminio/target-bucket/

# 批量移動
mc mv myminio/mybucket/temp/*.log myminio/mybucket/logs/

# 顯示詳細信息
mc mv --verbose myminio/mybucket/file.txt myminio/mybucket/archive/

ls - 列出文件/對象

# 基本語法
mc ls [FLAGS] TARGET

# 列出bucket中的所有對象
mc ls myminio/mybucket/

# 遞歸列出所有子目錄
mc ls --recursive myminio/mybucket/

# 顯示詳細信息(大小、時間等)
mc ls --recursive --summarize myminio/mybucket/

# 只顯示目錄
mc ls --recursive myminio/mybucket/ | grep "PRE"

# 按時間排序
mc ls --recursive myminio/mybucket/ | sort -k4

# 列出所有bucket
mc ls myminio/

# 顯示人類可讀的文件大小
mc ls --recursive --humanize myminio/mybucket/

# 列出不完整的上傳
mc ls --incomplete myminio/mybucket/

# 列出所有版本
mc ls --versions myminio/mybucket/file.txt

cat - 顯示文件內容

# 基本語法
mc cat [FLAGS] TARGET

# 顯示文件內容
mc cat myminio/mybucket/file.txt

# 顯示文件的前幾行
mc cat myminio/mybucket/file.txt | head -10

# 顯示文件的後幾行
mc cat myminio/mybucket/file.txt | tail -10

# 顯示多個文件內容
mc cat myminio/mybucket/file1.txt myminio/mybucket/file2.txt

head - 顯示文件開頭

# 基本語法
mc head [FLAGS] TARGET

# 顯示文件前10行(默認)
mc head myminio/mybucket/file.txt

# 顯示文件前20行
mc head --lines 20 myminio/mybucket/file.txt

# 顯示文件前1KB
mc head --bytes 1024 myminio/mybucket/file.txt

tail - 顯示文件結尾

# 基本語法
mc tail [FLAGS] TARGET

# 顯示文件後10行(默認)
mc tail myminio/mybucket/file.txt

# 顯示文件後20行
mc tail --lines 20 myminio/mybucket/file.txt

# 持續監控文件變化
mc tail --follow myminio/mybucket/log-file.txt

find - 查找文件

# 基本語法
mc find [FLAGS] TARGET

# 查找所有文件
mc find myminio/mybucket/

# 按名稱查找
mc find myminio/mybucket/ --name "*.jpg"

# 按大小查找(大於10MB)
mc find myminio/mybucket/ --larger 10MB

# 按大小查找(小於1MB)
mc find myminio/mybucket/ --smaller 1MB

# 按時間查找(7天前)
mc find myminio/mybucket/ --older 7d

# 按時間查找(最近3天)
mc find myminio/mybucket/ --newer 3d

# 組合條件查找
mc find myminio/mybucket/ --name "*.log" --older 30d

# 查找並執行操作
mc find myminio/mybucket/ --name "*.tmp" --exec "mc rm {}"

# 查找空文件
mc find myminio/mybucket/ --size 0

# 按路徑深度限制
mc find myminio/mybucket/ --maxdepth 2

du - 磁盤使用統計

# 基本語法
mc du [FLAGS] TARGET

# 顯示bucket使用情況
mc du myminio/mybucket/

# 顯示所有bucket使用情況
mc du myminio/

# 顯示詳細統計
mc du --recursive myminio/mybucket/

# 按深度統計
mc du --depth 2 myminio/mybucket/

# 人類可讀格式
mc du --humanize myminio/mybucket/

diff - 比較文件/目錄差異

# 基本語法
mc diff [FLAGS] FIRST SECOND

# 比較本地目錄和MinIO bucket
mc diff /path/to/local/directory/ myminio/mybucket/directory/

# 比較兩個MinIO bucket
mc diff myminio/bucket1/ myminio/bucket2/

# 顯示詳細差異
mc diff --verbose /path/to/local/ myminio/mybucket/

# 只顯示不同的文件
mc diff --diff /path/to/local/ myminio/mybucket/

# 遞歸比較
mc diff --recursive /path/to/local/ myminio/mybucket/

mirror - 鏡像同步

# 基本語法
mc mirror [FLAGS] SOURCE TARGET

# 將本地目錄同步到MinIO
mc mirror /path/to/local/directory/ myminio/mybucket/

# 將MinIO同步到本地
mc mirror myminio/mybucket/ /path/to/local/directory/

# 在兩個MinIO bucket間同步
mc mirror myminio/source-bucket/ myminio/target-bucket/

# 刪除目標中多餘的文件
mc mirror --remove /path/to/source/ myminio/mybucket/

# 覆蓋已存在的文件
mc mirror --overwrite /path/to/source/ myminio/mybucket/

# 排除特定文件
mc mirror --exclude "*.tmp" /path/to/source/ myminio/mybucket/

# 只同步新文件
mc mirror --skip-errors /path/to/source/ myminio/mybucket/

# 顯示詳細進度
mc mirror --verbose /path/to/source/ myminio/mybucket/

# 監控模式(持續同步)
mc mirror --watch /path/to/source/ myminio/mybucket/

pipe - 管道操作

# 基本語法
mc pipe [FLAGS] TARGET

# 從標準輸入上傳
echo "Hello World" | mc pipe myminio/mybucket/hello.txt

# 從文件內容上傳
cat /path/to/file.txt | mc pipe myminio/mybucket/piped-file.txt

# 從命令輸出上傳
date | mc pipe myminio/mybucket/current-time.txt
ps aux | mc pipe myminio/mybucket/process-list.txt
df -h | mc pipe myminio/mybucket/disk-usage.txt

# 壓縮後通過管道上傳
tar czf - /path/to/directory | mc pipe myminio/mybucket/backup.tar.gz
gzip -c /path/to/large-file.txt | mc pipe myminio/mybucket/compressed-file.txt.gz

# 數據庫備份通過管道上傳
mysqldump database_name | mc pipe myminio/mybucket/db-backup.sql
pg_dump database_name | mc pipe myminio/mybucket/postgres-backup.sql

# 日誌實時上傳
tail -f /var/log/app.log | mc pipe myminio/mybucket/logs/app-$(date +%Y%m%d).log

# 網絡數據通過管道上傳
curl -s https://api.example.com/data | mc pipe myminio/mybucket/api-data.json

# 加密後通過管道上傳
gpg --encrypt --armor -r recipient@example.com < /path/to/secret.txt | \
mc pipe myminio/mybucket/encrypted-secret.txt.asc

# 設置內容類型
echo '{"key": "value"}' | mc pipe --attr "Content-Type=application/json" myminio/mybucket/data.json

# 設置存儲類別
large_data_command | mc pipe --storage-class REDUCED_REDUNDANCY myminio/mybucket/large-data.bin

mc在MinIO中創建用户創建policy用户和policy的綁定(minio)_上傳_11

event - 事件通知管理

# 基本語法
mc event [FLAGS] COMMAND TARGET

# 添加事件通知
mc event add myminio/mybucket arn:minio:sqs::1:webhook --event put

# 添加多種事件類型的通知
mc event add myminio/mybucket arn:minio:sqs::1:webhook --event put,delete

# 添加帶前綴過濾的事件通知
mc event add myminio/mybucket arn:minio:sqs::1:webhook --event put --prefix images/

# 添加帶後綴過濾的事件通知
mc event add myminio/mybucket arn:minio:sqs::1:webhook --event put --suffix .jpg

# 列出所有事件通知配置
mc event list myminio/mybucket

# 刪除事件通知
mc event remove myminio/mybucket arn:minio:sqs::1:webhook

# 刪除所有事件通知
mc event remove myminio/mybucket --force

# 支持的事件類型示例
mc event add myminio/mybucket arn:minio:sqs::1:webhook --event put,delete,get

# 完整的事件配置示例
mc event add myminio/mybucket arn:minio:sqs::1:webhook \
  --event put,delete \
  --prefix logs/ \
  --suffix .log

mc在MinIO中創建用户創建policy用户和policy的綁定(minio)_上傳_12

mc在MinIO中創建用户創建policy用户和policy的綁定(minio)_顯示文件_13

mc在MinIO中創建用户創建policy用户和policy的綁定(minio)_顯示文件_14

gowebhook.go源代碼(AI編寫)

package main

import (
	"encoding/json"
	"fmt"
	"io"
	"log"
	"net/http"
	"os"
	"time"
)

// MinIO事件結構體定義
type MinIOEvent struct {
	EventVersion string    `json:"eventVersion"`
	EventSource  string    `json:"eventSource"`
	AwsRegion    string    `json:"awsRegion"`
	EventTime    time.Time `json:"eventTime"`
	EventName    string    `json:"eventName"`
	UserIdentity struct {
		PrincipalID string `json:"principalId"`
	} `json:"userIdentity"`
	RequestParameters struct {
		PrincipalID     string `json:"principalId"`
		Region          string `json:"region"`
		SourceIPAddress string `json:"sourceIPAddress"`
	} `json:"requestParameters"`
	ResponseElements struct {
		XAmzRequestID string `json:"x-amz-request-id"`
		XAmzID2       string `json:"x-amz-id-2"`
	} `json:"responseElements"`
	S3 struct {
		S3SchemaVersion string `json:"s3SchemaVersion"`
		ConfigurationID string `json:"configurationId"`
		Bucket          struct {
			Name          string `json:"name"`
			OwnerIdentity struct {
				PrincipalID string `json:"principalId"`
			} `json:"ownerIdentity"`
			Arn string `json:"arn"`
		} `json:"bucket"`
		Object struct {
			Key       string `json:"key"`
			Size      int64  `json:"size"`
			ETag      string `json:"eTag"`
			VersionID string `json:"versionId"`
			Sequencer string `json:"sequencer"`
		} `json:"object"`
	} `json:"s3"`
	Source struct {
		Host      string `json:"host"`
		Port      string `json:"port"`
		UserAgent string `json:"userAgent"`
	} `json:"source"`
}

type MinIOEventRecord struct {
	Records []MinIOEvent `json:"Records"`
}

// Webhook處理器
func webhookHandler(w http.ResponseWriter, r *http.Request) {
	// 只接受POST請求
	if r.Method != http.MethodPost {
		http.Error(w, "只支持POST方法", http.StatusMethodNotAllowed)
		return
	}

	// 讀取請求體
	body, err := io.ReadAll(r.Body)
	if err != nil {
		log.Printf("讀取請求體失敗: %v", err)
		http.Error(w, "讀取請求體失敗", http.StatusBadRequest)
		return
	}
	defer r.Body.Close()

	// 記錄原始請求信息
	log.Printf("收到webhook請求:")
	log.Printf("  方法: %s", r.Method)
	log.Printf("  URL: %s", r.URL.String())
	log.Printf("  遠程地址: %s", r.RemoteAddr)
	log.Printf("  User-Agent: %s", r.UserAgent())
	log.Printf("  Content-Type: %s", r.Header.Get("Content-Type"))
	log.Printf("  Content-Length: %s", r.Header.Get("Content-Length"))

	// 打印原始JSON數據
	log.Printf("原始JSON數據:")
	log.Printf("%s", string(body))

	// 解析MinIO事件
	var eventRecord MinIOEventRecord
	if err := json.Unmarshal(body, &eventRecord); err != nil {
		log.Printf("解析JSON失敗: %v", err)
		// 即使解析失敗也返回成功,避免MinIO重試
		w.Header().Set("Content-Type", "application/json")
		w.WriteHeader(http.StatusOK)
		json.NewEncoder(w).Encode(map[string]string{"status": "received", "error": err.Error()})
		return
	}

	// 處理每個事件記錄
	for i, event := range eventRecord.Records {
		log.Printf("處理事件記錄 %d:", i+1)
		processEvent(event)
	}

	// 返回成功響應
	w.Header().Set("Content-Type", "application/json")
	w.WriteHeader(http.StatusOK)
	response := map[string]interface{}{
		"status":    "success",
		"processed": len(eventRecord.Records),
		"timestamp": time.Now(),
	}
	json.NewEncoder(w).Encode(response)
}

// 處理單個事件
func processEvent(event MinIOEvent) {
	log.Printf("=== MinIO事件詳情 ===")
	log.Printf("事件名稱: %s", event.EventName)
	log.Printf("事件時間: %s", event.EventTime.Format("2006-01-02 15:04:05"))
	log.Printf("事件源: %s", event.EventSource)
	log.Printf("AWS區域: %s", event.AwsRegion)
	log.Printf("Bucket名稱: %s", event.S3.Bucket.Name)
	log.Printf("對象鍵: %s", event.S3.Object.Key)
	log.Printf("對象大小: %d 字節", event.S3.Object.Size)
	log.Printf("ETag: %s", event.S3.Object.ETag)
	log.Printf("版本ID: %s", event.S3.Object.VersionID)
	log.Printf("源IP地址: %s", event.RequestParameters.SourceIPAddress)
	log.Printf("請求ID: %s", event.ResponseElements.XAmzRequestID)

	// 根據事件類型執行不同的處理邏輯
	switch event.EventName {
	case "s3:ObjectCreated:Put":
		handleObjectCreated(event)
	case "s3:ObjectCreated:Post":
		handleObjectCreated(event)
	case "s3:ObjectCreated:Copy":
		handleObjectCreated(event)
	case "s3:ObjectRemoved:Delete":
		handleObjectDeleted(event)
	case "s3:ObjectAccessed:Get":
		handleObjectAccessed(event)
	case "s3:ObjectAccessed:Head":
		handleObjectAccessed(event)
	default:
		log.Printf("未知事件類型: %s", event.EventName)
	}

	log.Printf("==================")
}

// 處理對象創建事件
func handleObjectCreated(event MinIOEvent) {
	log.Printf("🔵 對象創建事件")
	log.Printf("新文件: %s/%s", event.S3.Bucket.Name, event.S3.Object.Key)
	log.Printf("文件大小: %d 字節", event.S3.Object.Size)

	// 這裏可以添加自定義處理邏輯
	// 例如:發送通知、觸發工作流、記錄到數據庫等
}

// 處理對象刪除事件
func handleObjectDeleted(event MinIOEvent) {
	log.Printf("🔴 對象刪除事件")
	log.Printf("刪除文件: %s/%s", event.S3.Bucket.Name, event.S3.Object.Key)

	// 這裏可以添加自定義處理邏輯
	// 例如:清理相關數據、發送刪除通知等
}

// 處理對象訪問事件
func handleObjectAccessed(event MinIOEvent) {
	log.Printf("🟡 對象訪問事件")
	log.Printf("訪問文件: %s/%s", event.S3.Bucket.Name, event.S3.Object.Key)
	log.Printf("訪問來源: %s", event.RequestParameters.SourceIPAddress)

	// 這裏可以添加自定義處理邏輯
	// 例如:記錄訪問日誌、統計下載次數等
}

// 健康檢查端點
func healthHandler(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "application/json")
	w.WriteHeader(http.StatusOK)
	response := map[string]interface{}{
		"status":    "healthy",
		"timestamp": time.Now(),
		"service":   "minio-webhook",
	}
	json.NewEncoder(w).Encode(response)
}

// 根路徑處理器
func rootHandler(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "text/html; charset=utf-8")
	html := `
<!DOCTYPE html>
<html>
<head>
    <title>MinIO Webhook Server</title>
    <style>
        body { font-family: Arial, sans-serif; margin: 40px; }
        .container { max-width: 800px; margin: 0 auto; }
        .endpoint { background: #f5f5f5; padding: 10px; margin: 10px 0; border-radius: 4px; }
        .method { color: #007bff; font-weight: bold; }
    </style>
</head>
<body>
    <div class="container">
        <h1>MinIO Webhook Server</h1>
        <p>這是一個用於接收MinIO事件通知的Webhook服務器。</p>
        
        <h2>可用端點:</h2>
        <div class="endpoint">
            <span class="method">POST</span> /webhook - 接收MinIO事件通知
        </div>
        <div class="endpoint">
            <span class="method">GET</span> /health - 健康檢查
        </div>
        
        <h2>使用方法:</h2>
        <p>在MinIO中配置webhook通知目標為: <code>http://your-server:8080/webhook</code></p>
        
        <h2>服務狀態:</h2>
        <p>服務器運行時間: ` + time.Now().Format("2006-01-02 15:04:05") + `</p>
    </div>
</body>
</html>`
	fmt.Fprint(w, html)
}

func main() {
	// 獲取端口號,默認8080
	port := os.Getenv("PORT")
	if port == "" {
		port = "8080"
	}

	// 設置日誌格式
	log.SetFlags(log.LstdFlags | log.Lshortfile)

	// 註冊路由
	http.HandleFunc("/", rootHandler)
	http.HandleFunc("/webhook", webhookHandler)
	http.HandleFunc("/health", healthHandler)

	// 啓動服務器
	log.Printf("MinIO Webhook服務器啓動在端口 %s", port)
	log.Printf("Webhook端點: http://localhost:%s/webhook", port)
	log.Printf("健康檢查: http://localhost:%s/health", port)
	log.Printf("按 Ctrl+C 停止服務器")

	if err := http.ListenAndServe(":"+port, nil); err != nil {
		log.Fatalf("服務器啓動失敗: %v", err)
	}
}