【一】Docker部署Minio容器
【1】Minio容器介绍
-
Minio是一个开源的对象存储服务器,使用Apache License v2.0开源协议。
- 它提供了一个存储桶(bucket)的概念,类似于文件系统中的目录,用于存储对象文件。
- Minio与亚马逊S3云存储服务兼容,使得它可以轻松地与现有的S3应用程序集成。
-
Minio的优势在于其简洁和高性能。
- 它被设计成轻量级的,并且具有低延迟和高吞吐量的特点。
- 这使得Minio非常适合存储大容量的非结构化数据,例如图像、视频、日志文件、备份数据以及容器或虚拟机镜像等。
- 而且,Minio没有任何限制,一个对象文件可以是任意大小,从几KB到最大5TB不等。
-
Minio通过使用分布式架构来实现高可用性和冗余备份。
- 您可以配置多个Minio服务器,形成一个分布式集群来确保数据的安全性和可靠性。
- 此外,Minio还支持数据加密和访问控制,使您能够根据需要对数据进行保护和管理。
-
总之,Minio是一个功能强大且易于使用的对象存储服务器,适用于各种场景,包括数据存储、数据备份、容器存储等。
- 通过与亚马逊S3兼容的API,Minio能够轻松地与现有的应用程序集成,为您提供方便和高效的存储解决方案。
【2】寻找Minio镜像
【3】下载Minio镜像
(1)下载最新版本镜像
docker pull minio/minio
(2)下载指定版本镜像
docker pull minio/minio:RELEASE.2022-06-20T23-13-45Z.fips
下载指定版本的Minio镜像 (xxx指具体版本号)
(3)下载过程
Using default tag: latest
latest: Pulling from minio/minio
0c10cd59e10e: Pull complete
ee2351f734c9: Pull complete
6938b5623639: Pull complete
52c7cc767226: Pull complete
234b624c4f30: Pull complete
67f2303e832e: Pull complete
Digest: sha256:d6369c50d12a201b8fe72458c97fba79a50980184440b1e2fe93634dbf0ef682
Status: Downloaded newer image for minio/minio:latest
docker.io/minio/minio:latest
REPOSITORY TAG IMAGE ID CREATED SIZE
minio/minio latest b28473c6b8d0 2 days ago 276MB
【4】创建目录
- 一个用来存放配置,一个用来存储上传文件的目录
- 启动前需要先创建Minio外部挂载的配置文件( /home/minio/config)和存储上传文件的目录( /home/minio/data)
mkdir -p /data/minio/config
mkdir -p /data/minio/data
# cd /data
# ls
minio
# cd minio
# ls
config data
【5】创建Minio容器并运行
docker run -p 9011:9011 -p 9010:9010 \
--name minio \
-d --restart=always \
-e "MINIO_ACCESS_KEY=dream" \
-e "MINIO_SECRET_KEY=dream521" \
-v /data/minio/data:/data \
-v /data/minio/config:/root/.minio \
minio/minio server \
/data --console-address ":9010" -address ":9011"
- 9090端口指的是minio的客户端端口
- MINIO_ACCESS_KEY :账号
- MINIO_SECRET_KEY :密码(账号长度必须大于等于5,密码长度必须大于等于8位)
- 配置文件路径要和上面的自定义路径一样
- 存储文件路径要和上面的自定义路径一样
docker run -p 9010:9010 -p 9011:9011 --net=host --name minio -d --restart=always -e "MINIO_ACCESS_KEY=dream" -e "MINIO_SECRET_KEY=dream521" -v /data/minio/data:/data -v /data/minio/config:/root/.minio minio/minio server /data --console-address ":9010" -address ":9011"
【6】操作Minio
(1)登录页面
(2)登陆成功
(3)创建用户
(4)创建 Create Group
(5)创建accessKey和secretKey
- 文件名:credentials.json
- 文件内容
{"url":"http://IP/api/v1/service-account-credentials","accessKey":"秘钥","secretKey":"秘钥","api":"s3v4","path":"auto"}
- 以上内容是自动生成的,我填文字的部分都是自动生成的
- IP:自己的服务器IP
- 秘钥:上面自动生成的
- 秘钥:上面自动生成的
(6)创建桶(Bucket)
(7)上传文件
【7】SDK操作
(1)相关链接
(2)Java 操作上传文件
#低版本的okhttp会报错提示
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>4.9.0</version>
</dependency>
<dependency>
<groupId>io.minio</groupId>
<artifactId>minio</artifactId>
<version>8.4.2</version>
<exclusions>
<exclusion>
<artifactId>okhttp</artifactId>
<groupId>com.squareup.okhttp3</groupId>
</exclusion>
</exclusions>
</dependency>
import io.minio.BucketExistsArgs;
import io.minio.MakeBucketArgs;
import io.minio.MinioClient;
import io.minio.UploadObjectArgs;
import io.minio.errors.MinioException;
import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
public class FileUploader {
public static void main(String[] args) throws IOException, NoSuchAlgorithmException, InvalidKeyException {
try {
// Create a minioClient with the MinIO server playground, its access key and secret key.
MinioClient minioClient =
MinioClient.builder()
.endpoint("http://192.168.124.132:9000")
.credentials("XO1JDovW2FTmGaBb", "uG6wMfylUnOVH5WzwxqnldOWw2dMshNX")
.build();
// Make 'asiatrip' bucket if not exist.
boolean found = minioClient.bucketExists(BucketExistsArgs.builder().bucket("public").build());
if (!found) {
// Make a new bucket called 'asiatrip'.
minioClient.makeBucket(MakeBucketArgs.builder().bucket("public").build());
} else {
System.out.println("Bucket 'public' already exists.");
}
// Upload '/home/user/Photos/asiaphotos.zip' as object name 'asiaphotos-2015.zip' to bucket
// 'asiatrip'.
minioClient.uploadObject(
UploadObjectArgs.builder()
.bucket("public")
.object("credentials.json")
.filename("C:/Users/lai.huanxiong/Downloads/credentials.json")
.build());
System.out.println("'C:/Users/lai.huanxiong/Downloads/credentials.json' is successfully uploaded as " + "object 'credentials.json' to bucket 'public'.");
} catch (MinioException e) {
System.out.println("Error occurred: " + e);
System.out.println("HTTP trace: " + e.httpTrace());
}
}
}
(3)Python 操作上传文件
[1]最低要求
[2]安装第三方库
pip3 install minio
git clone https://github.com/minio/minio-py
cd minio-py
python setup.py install
[3]快速入门示例
- 此示例程序连接到与 S3 兼容的对象存储服务器,在该服务器上创建一个存储桶,然后将文件上传到该存储桶。
- 您需要以下项目才能连接到与 S3 兼容的对象存储服务器:
参数 |
描述 |
端点 |
指向 S3 服务的网址。 |
访问密钥 |
S3 服务中账户的访问密钥(也称为用户 ID)。 |
密钥 |
S3 服务中账户的私有密钥(也称为密码)。 |
from minio import Minio
from minio.error import S3Error
def main():
# Create a client with the MinIO server playground, its access key
# and secret key.
client = Minio(
"play.min.io",
access_key="Q3AM3UQ867SPQQA43P2F",
secret_key="zuf+tfteSlswRu7BJ86wekitnifILbZam1KYY3TG",
)
# Make 'asiatrip' bucket if not exist.
found = client.bucket_exists("asiatrip")
if not found:
client.make_bucket("asiatrip")
else:
print("Bucket 'asiatrip' already exists")
# Upload '/home/user/Photos/asiaphotos.zip' as object name
# 'asiaphotos-2015.zip' to bucket 'asiatrip'.
client.fput_object(
"asiatrip", "asiaphotos-2015.zip", "/home/user/Photos/asiaphotos.zip",
)
print(
"'/home/user/Photos/asiaphotos.zip' is successfully uploaded as "
"object 'asiaphotos-2015.zip' to bucket 'asiatrip'."
)
if __name__ == "__main__":
try:
main()
except S3Error as exc:
print("error occurred.", exc)
$ python file_uploader.py
'/home/user/Photos/asiaphotos.zip' is successfully uploaded as object 'asiaphotos-2015.zip' to bucket 'asiatrip'.
$ mc ls play/asiatrip/
[2016-06-02 18:10:29 PDT] 82KiB asiaphotos-2015.zip
【二】基于Python版本的SDK封装
- 特别感谢博主提供的思路支持
- 本次封装基于Minio官网提供的Python SDK 开发者文档进行二次封装
【三】封装结构树
├── MinioPySdk
├── imgs # README.md 用到的静态图片
├── __init__.py # 初始化程序,可以将MinioPySdk直接导入,而不需要单独导入函数
├── py_sdk_minio.py # 项目主应用,开发时的代码保存
├── settings.py # 项目主应用配置文件(配置必填参数)
├── test.py # 项目主应用测试文件(含方法使用说明)
├── README.md # 项目主应用介绍文件
# -*-coding: Utf-8 -*-
# @File : __init__ .py
# author: Chimengmeng
# blog_url : https://www.cnblogs.com/dream-ze/
# Time:2023/8/13
from .py_sdk_minio import *
from .settings import *
# -*-coding: Utf-8 -*-
# @File : settings .py
# author: Chimengmeng
# blog_url : https://www.cnblogs.com/dream-ze/
# Time:2023/8/13
# endpoint指定的是你Minio的远程IP及端口
ENDPOINT = "43.138.48.158:9011"
# accesskey指定的是你的Minio服务器访问key
ACCESS_KEY = "7FGId3bewvgBq75Upf0Q"
# secret_key指定的是你登录时需要用的key,类似密码
SECRET_KEY = "5wvGpsF9f058sSBq9A3XJ06qQezLFlKnSu0vKNkh"
# secure指定是否以安全模式创建Minio连接,建议为False
SECURE = False
# 必须指定一个默认存储桶名称
BUCKET_NAME = 'testbucket'
# -*-coding: Utf-8 -*-
# @File : py_sdk_minio .py
# author: Chimengmeng
# blog_url : https://www.cnblogs.com/dream-ze/
# Time:2023/8/13
import os
import pytz
from datetime import timedelta
from minio import Minio
from minio.commonconfig import CopySource
from minio.deleteobjects import DeleteObject
from minio.error import MinioException
from PIL import Image
# 桶相关操作
class BucketOperation(object):
def __init__(self, endpoint, access_key, secret_key, bucket_name, secure=False):
'''
:param endpoint: IP:PORT(必传)
:param access_key: 访问key,类似于用户名(必传)
:param secret_key: 访问密钥,类似于密码(必传)
:param bucket_name: 初识桶名(必传)
:param secure: 以安全模式创建Minio连接,建议默认为 False (可选)
:param back_dict: 反馈信息字典
result : 执行成功/失败
tag_bucket_name :当前桶名
msg : 返回的单条消息
'''
self.endpoint = endpoint
self.access_key = access_key
self.secret_key = secret_key
self.secure = secure
self.bucket_name = bucket_name
self.back_dict = {"result": True, "tag_bucket_name": "", "msg": "", "msg_list": []}
self.minioClient = Minio(
endpoint=endpoint,
access_key=access_key,
secret_key=secret_key,
secure=secure
)
# 校验目标桶名
def get_tag_bucket_name(self, tag_bucket_name=None):
'''
:param tag_bucket_name: 校验桶名
:return: 返回桶名
'''
self.back_dict['tag_bucket_name'] = tag_bucket_name
if tag_bucket_name:
return tag_bucket_name
else:
return self.bucket_name
# 创建桶 / 校验桶
def create_bucket(self, tag_bucket_name=None):
'''
:param tag_bucket_name: 目标桶名,默认是初始化的桶名,可以自创建桶
:return:
'''
tag_bucket_name = self.get_tag_bucket_name(tag_bucket_name)
try:
if self.minioClient.bucket_exists(bucket_name=tag_bucket_name): # bucket_exists:检查桶是否存在
self.back_dict['msg'] = f"目标存储桶 {tag_bucket_name} 已经存在"
return self.back_dict
else:
self.minioClient.make_bucket(tag_bucket_name)
self.back_dict['msg'] = f"目标存储桶 {tag_bucket_name} 创建成功"
except MinioException as err:
self.back_dict['result'] = False
self.back_dict['msg'] = f"初始化存储桶失败"
self.back_dict['error'] = err
return self.back_dict
# 列出所有的存储桶 list_buckets函数
def get_bucket_list(self, tag_bucket_name=None):
tag_bucket_name = self.get_tag_bucket_name(tag_bucket_name)
try:
buckets = self.minioClient.list_buckets()
for bucket in buckets:
bucket_dict = {}
bucket_dict['bucket_name'] = bucket.name
bucket_create_time_utc = bucket.creation_date
bucket_create_time_sh = bucket_create_time_utc.astimezone(pytz.timezone('Asia/Shanghai')) # 获取中国北京时区的信息
bucket_dict['bucket_create_time_utc'] = bucket_create_time_utc.strftime("%Y-%m-%d %H:%M:%S")
bucket_dict['bucket_create_time_sh'] = bucket_create_time_sh.strftime("%Y-%m-%d %H:%M:%S")
self.back_dict['msg_list'].append(bucket_dict)
self.back_dict['msg'] = '存储桶列表获取成功'
except MinioException as err:
self.back_dict['result'] = False
self.back_dict['msg'] = f"获取桶列表失败"
self.back_dict['error'] = err
return self.back_dict
# 删除存储桶(单个存储桶)
def get_remove_bucket(self, tag_bucket_name):
'''
:param tag_bucket_name: 当前桶名称
:return: 返回信息字典
'''
try:
self.minioClient.remove_bucket(tag_bucket_name)
self.back_dict['tag_bucket_name'] = self.bucket_name
self.back_dict['msg'] = f"目标存储桶 {tag_bucket_name} 删除成功"
except MinioException as err:
self.back_dict['result'] = False
self.back_dict['msg'] = f"目标存储桶 {tag_bucket_name} 删除失败"
self.back_dict['error'] = err
return self.back_dict
# 列出目标存储桶中所有对象 或者使用 list_objects_v2也可
def get_bucket_files(self, tag_bucket_name=None):
'''
:param tag_bucket_name: 当前桶名称
:return: 返回信息字典
'''
tag_bucket_name = self.get_tag_bucket_name(tag_bucket_name)
try:
self.back_dict['msg_list'] = []
object_dict = {}
# prefix用于过滤的对象名称前缀
# objects = self.minioClient.list_objects('my_bucket', prefix='photos/') # 列出指定前缀开头的对象
# objects = self.minioClient.list_objects('my_bucket', prefix='photos/', recursive=False) # 仅列举指定前缀下的直接对象,不递归子目录
objects = self.minioClient.list_objects(tag_bucket_name, prefix=None, recursive=True)
for obj in objects:
object_dict['obj_bucket_name'] = obj.bucket_name
object_dict['obj_name'] = obj.object_name
bucket_create_time_utc = obj.last_modified
bucket_create_time_sh = bucket_create_time_utc.astimezone(pytz.timezone('Asia/Shanghai')) # 获取中国北京时区的信息
object_dict['last_modified_utc'] = bucket_create_time_utc.strftime("%Y-%m-%d %H:%M:%S")
object_dict['last_modified_sh'] = bucket_create_time_sh.strftime("%Y-%m-%d %H:%M:%S")
# etag : 对象的唯一标识符
object_dict['etag'] = obj.etag
object_dict['size'] = obj.size
object_dict['content_type'] = obj.content_type
self.back_dict['msg_list'].append(object_dict)
self.back_dict['msg'] = f"目标存储桶 {tag_bucket_name} 获取所有对象成功"
except MinioException as err:
self.back_dict['result'] = False
self.back_dict['msg'] = f"目标存储桶 {tag_bucket_name} 获取所有对象失败"
self.back_dict['error'] = err
return self.back_dict
# 列出存储桶中未完整上传的对象(废弃)
def get_list_incomplete_uploads(self, tag_bucket_name=None):
'''
:param tag_bucket_name: 当前桶名称
:return: 返回信息字典
'''
tag_bucket_name = self.get_tag_bucket_name(tag_bucket_name)
try:
uploads = self.minioClient.list_incomplete_uploads(tag_bucket_name, prefix=None, recursive=True)
for obj in uploads:
res = f'当前存储桶:>> {obj.bucket_name} 文件名:>> {obj.object_name} 上传id:>> {obj.upload_id} 文件大小:>> {obj.size}'
print(res)
except MinioException as err:
res = f"温馨提示 : 出错啦!错误是 :>>{err}"
print(res)
# 获取存储桶的当前策略
def bucket_policy(self, tag_bucket_name=None):
'''
:param tag_bucket_name: 当前桶名称
:return: 返回信息字典
'''
tag_bucket_name = self.get_tag_bucket_name(tag_bucket_name)
try:
policy = self.minioClient.get_bucket_policy(tag_bucket_name)
self.back_dict['msg'] = f"目标存储桶 {tag_bucket_name} 获取存储策略成功"
self.back_dict['policy'] = policy
except MinioException as err:
self.back_dict['result'] = False
self.back_dict['msg'] = f"目标存储桶 {tag_bucket_name} 获取存储策略失败"
self.back_dict['error'] = err
return self.back_dict
# 给指定的存储桶设置存储桶策略
def get_set_bucket_policy(self, tag_bucket_name, policy):
'''
:param tag_bucket_name: 当前桶名称
:param policy: 存储桶策略
:return: 返回信息字典
'''
tag_bucket_name = self.get_tag_bucket_name(tag_bucket_name)
try:
'''
# 示例 :
policy = """
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::123456789012:user/Alice"
},
"Action": [
"s3:GetObject",
"s3:PutObject"
],
"Resource": "arn:aws:s3:::test1/*"
}
]
}
"""
'''
self.minioClient.set_bucket_policy(tag_bucket_name, policy)
self.back_dict['msg'] = f"目标存储桶 存储策略 设置成功"
# self.back_dict['policy'] = policy
except MinioException as err:
self.back_dict['result'] = False
self.back_dict['msg'] = f"目标存储桶 {tag_bucket_name} 设置存储策略失败"
self.back_dict['error'] = err
return self.back_dict
# 获取存储桶的通知配置(成功)
def get_bucket_notification(self, tag_bucket_name=None):
'''
:param tag_bucket_name: 当前桶名称
:return: 返回信息字典
'''
tag_bucket_name = self.get_tag_bucket_name(tag_bucket_name)
try:
notification = self.minioClient.get_bucket_notification(tag_bucket_name)
self.back_dict['msg'] = f"目标存储桶 {tag_bucket_name} 通知配置 获取成功"
self.back_dict['notification'] = notification
except MinioException as err:
self.back_dict['result'] = False
self.back_dict['msg'] = f"目标存储桶 {tag_bucket_name} 通知配置 获取失败"
self.back_dict['error'] = err
return self.back_dict
# 设置存储桶的通知配置(失败)
def re_set_bucket_notification(self, notification_config, tag_bucket_name=None):
'''
:param notification_config: 通知配置
:param tag_bucket_name: 当前桶名称
:return: 返回信息字典
'''
'''
Example::
config = NotificationConfig(
queue_config_list=[
QueueConfig(
"QUEUE-ARN-OF-THIS-BUCKET",
["s3:ObjectCreated:*"],
config_id="1",
prefix_filter_rule=PrefixFilterRule("abc"),
),
],
)
:param notification_config: 通知配置
:param tag_bucket_name: 目标桶
:return:
'''
tag_bucket_name = self.get_tag_bucket_name(tag_bucket_name)
try:
# 设置存储桶的通知配置
res = self.minioClient.set_bucket_notification(tag_bucket_name, config=notification_config)
self.back_dict['msg'] = f"目标存储桶 {tag_bucket_name} 通知配置 设置成功"
self.back_dict['notification_config'] = notification_config
except MinioException as err:
self.back_dict['result'] = False
self.back_dict['tag_bucket_name'] = tag_bucket_name
self.back_dict['msg'] = f"目标存储桶 {tag_bucket_name} 通知配置 设置失败"
self.back_dict['error'] = err
self.back_dict['notification_config'] = notification_config
return self.back_dict
# 移除存储桶上的所有通知(失败)
def re_remove_all_bucket_notifications(self, tag_bucket_name=None):
'''
:param tag_bucket_name: 存储桶的名称
:return: 返回信息字典
'''
tag_bucket_name = self.get_tag_bucket_name(tag_bucket_name)
try:
# 移除存储桶上的所有通知
res = self.minioClient.delete_bucket_notification(tag_bucket_name)
self.back_dict['msg'] = f"目标存储桶 {tag_bucket_name} 通知配置 移除成功"
except MinioException as err:
self.back_dict['result'] = False
self.back_dict['msg'] = f"目标存储桶 {tag_bucket_name} 通知配置 移除失败"
self.back_dict['error'] = err
return self.back_dict
# 监听存储桶的通知
def listen_bucket_notification(self, prefix, suffix, events, tag_bucket_name=None):
'''
:param prefix: 对象前缀,用于匹配以指定前缀开头的对象。可选参数,默认为空字符串。
:param suffix:对象后缀,用于匹配以指定后缀结尾的对象。可选参数,默认为空字符串。
:param events: 需要监听的事件类型。可选参数,默认为`s3:ObjectCreated:*`、`s3:ObjectRemoved:*`、`s3:ObjectAccessed:*`三种事件类型。
:param tag_bucket_name: 存储桶的名称
:return: 返回信息字典
'''
tag_bucket_name = self.get_tag_bucket_name(tag_bucket_name)
try:
# 监听存储桶的通知
for event in self.minioClient.listen_bucket_notification(tag_bucket_name, prefix=prefix, suffix=suffix,
events=events):
self.back_dict['result'] = True
self.back_dict['msg'] = f"目标存储桶 {tag_bucket_name} 监听成功"
self.back_dict['event'] = event
return self.back_dict
except MinioException as err:
self.back_dict['result'] = False
self.back_dict['msg'] = f"目标存储桶 {tag_bucket_name} 监听失败"
self.back_dict['error'] = err
return self.back_dict
class FileOperation():
def __init__(self, bucket_obj):
'''
:param bucket_obj: 存储桶对象 (必传)
minioClient : 父类的链接对象
back_dict : 返回信息字典
get_tag_bucket_name : 校验当前桶对象
'''
self.minioClient = bucket_obj.minioClient
self.bucket_name = bucket_obj.bucket_name
self.back_dict = bucket_obj.back_dict
self.get_tag_bucket_name = bucket_obj.get_tag_bucket_name
# 从桶中下载一个对象(支持txt、csv文件)并保存到指定路径
def load_object(self, save_file_path, tag_file_name, tag_bucket_name=None, start=0, end=0):
'''
:param save_file_path: 保存文件的路径
:param tag_file_name: 桶名称
:param tag_bucket_name: 文件名称
:param start: 区间起始位置
:param end: 区间结束位置
:return: 下载成功或失败的提示信息
'''
tag_bucket_name = self.get_tag_bucket_name(tag_bucket_name)
try:
data = self.minioClient.get_object(tag_bucket_name, tag_file_name, start, end) # 这里的data 是 WEBP 格式的数据
type_save_file_path = os.path.join(save_file_path, tag_file_name)
with open(type_save_file_path, 'wb') as file_data:
for d in data.stream(32 * 1024):
file_data.write(d)
type_file = tag_file_name.split('.')[-1].upper()
if type_file in ['PNG', 'JPG', 'WEBP', 'JPEG', 'GIF', 'TIFF', 'BMP', 'SVG']:
# 将WEBP图片转换为指定格式
image = Image.open(type_save_file_path).convert('RGB')
image.save(type_save_file_path, f"{type_file}")
else:
...
self.back_dict['msg'] = f"目标文件 {tag_file_name} 下载成功"
return self.back_dict
except Exception as err:
self.back_dict['result'] = False
self.back_dict['msg'] = f"目标存储桶 {tag_file_name} 下载失败"
self.back_dict['error'] = err
return self.back_dict
# 下载并将文件保存到本地
def fget_object(self, save_file_path, tag_file_name, tag_bucket_name=None):
"""
:param save_file_path: 保存文件的路径
:param tag_bucket_name: 桶名称
:param tag_file_name: 文件名称
:return:
"""
tag_bucket_name = self.get_tag_bucket_name(tag_bucket_name)
try:
save_file_path = os.path.join(save_file_path, tag_file_name)
res = self.minioClient.fget_object(tag_bucket_name, tag_file_name, save_file_path)
self.back_dict['msg'] = f"目标文件下载成功"
self.back_dict['addr'] = save_file_path
return self.back_dict
except MinioException as err:
self.back_dict['result'] = False
self.back_dict['msg'] = f"目标文件 {tag_file_name} 下载失败"
self.back_dict['error'] = err
return self.back_dict
# 拷贝对象存储服务上的源对象到一个新对象
# 注:该API支持的最大文件大小是5GB
# 可通过copy_conditions参数设置copy条件
# 经测试copy复制28M的文件需要663ms; 1.8G的压缩包需要53s
def get_copy_object(self, start_file_name, end_file_name=None, start_bucket_name=None, end_bucket_name=None):
"""
拷贝对象存储服务上的源对象到一个新对象
:param start_file_name: 源文件桶的文件名字
:param start_bucket_name: 源文件桶对象
:param end_file_name: 目标对象桶的文件名字
:param end_bucket_name: 目标桶对象
:param source_obj: source 对象 CopySource("my-sourcebucket", "my-sourceobject")
:return:
"""
tag_bucket_name = self.get_tag_bucket_name(end_bucket_name)
if end_file_name:
end_file_name = end_file_name
else:
end_file_name = start_file_name
source_obj = CopySource(start_bucket_name, start_file_name)
try:
copy_result = self.minioClient.copy_object(tag_bucket_name, end_file_name, source_obj)
self.back_dict['msg'] = f"源桶 :>> {start_bucket_name} 源文件 :>> {start_file_name} 目标桶 :>> {end_bucket_name} 目标文件 :>> {end_file_name} 拷贝成功"
self.back_dict['copy_result'] = copy_result
return self.back_dict
except MinioException as err:
self.back_dict['result'] = False
self.back_dict['msg'] = f"目标文件 {start_file_name} 拷贝失败"
self.back_dict['error'] = err
return self.back_dict
# 添加一个新的对象到对象存储服务
"""
单个对象的最大大小限制在5TB。put_object在对象大于5MiB时,自动使用multiple parts方式上传。
这样,当上传失败时,客户端只需要上传未成功的部分即可(类似断点上传)。
上传的对象使用MD5SUM签名进行完整性验证。
"""
def upload_object(self, upload_file_path, tag_bucket_name=None, tag_file_name=None, content_type=None):
'''
:param upload_file_path: 本地上传文件的路径
:param tag_bucket_name: 目标存储桶
:param tag_file_name: 当前存储文件在存储桶的文件名
:param content_type: 存储文件的类型(可根据需要选择) 指定上传的数据类型 "application/json"、"image/jpeg"、"text/plain"等。
:return:
'''
tag_bucket_name = self.get_tag_bucket_name(tag_bucket_name)
# 不选择类型
if not content_type:
try:
with open(upload_file_path, 'rb') as file_data:
file_stat = os.stat(upload_file_path)
res = self.minioClient.put_object(tag_bucket_name, tag_file_name, file_data, file_stat.st_size)
download_url = self.minioClient.presigned_get_object(bucket_name=tag_bucket_name,
object_name=tag_file_name,
expires=timedelta(days=7),
response_headers={
'x-amz-server-side-encryption': 'AES256'})
self.back_dict['msg'] = f"目标桶 {tag_bucket_name} 目标文件 {tag_file_name} 上传成功"
self.back_dict['download_url'] = download_url
return self.back_dict
except MinioException as err:
self.back_dict['result'] = False
self.back_dict['msg'] = f"目标文件 {tag_file_name} 上传失败"
self.back_dict['error'] = err
return self.back_dict
# 指定其他类型
else:
try:
with open(upload_file_path, 'rb') as file_data:
file_stat = os.stat(upload_file_path)
self.minioClient.put_object(tag_bucket_name, tag_file_name, file_data, file_stat.st_size,
content_type=content_type)
download_url = self.minioClient.presigned_get_object(bucket_name=tag_bucket_name,
object_name=tag_file_name,
expires=timedelta(days=7),
response_headers={
'x-amz-server-side-encryption': 'AES256'})
self.back_dict['msg'] = f"目标文件 {tag_file_name} 文件类型 {content_type} 上传成功"
self.back_dict['download_url'] = download_url
return self.back_dict
except MinioException as err:
self.back_dict['result'] = False
self.back_dict['msg'] = f"目标文件 {tag_file_name} 文件类型 {content_type} 上传失败"
self.back_dict['error'] = err
return self.back_dict
# 通过文件上传到对象中
def fput_object(self, tag_file_name=None, tag_bucket_name=None, upload_file_path=None, content_type=None):
'''
:param upload_file_path: 本地上传文件的路径
:param tag_bucket_name: 目标存储桶
:param tag_file_name: 当前存储文件在存储桶的文件名
:param content_type: 存储文件的类型(可根据需要选择) 指定上传的数据类型 "application/json"、"image/jpeg"、"text/plain"等。
:return:
'''
tag_bucket_name = self.get_tag_bucket_name(tag_bucket_name)
if not content_type:
try:
res = self.minioClient.fput_object(tag_bucket_name, tag_file_name, upload_file_path)
# 返回一个下载链接 : 有效期 7 天
download_url = self.minioClient.presigned_get_object(bucket_name=tag_bucket_name,
object_name=tag_file_name,
expires=timedelta(days=7),
response_headers={
'x-amz-server-side-encryption': 'AES256'})
self.back_dict['msg'] = f"目标文件 {tag_file_name} 上传成功"
self.back_dict['download_url'] = download_url
return self.back_dict
except MinioException as err:
self.back_dict['result'] = False
self.back_dict['msg'] = f"目标文件 {tag_file_name} 上传失败"
self.back_dict['error'] = err
return self.back_dict
else:
try:
res = self.minioClient.fput_object(tag_bucket_name, tag_file_name, upload_file_path,
content_type=content_type)
download_url = self.minioClient.presigned_get_object(bucket_name=tag_bucket_name,
object_name=tag_file_name,
expires=timedelta(days=7),
response_headers={
'x-amz-server-side-encryption': 'AES256'})
self.back_dict['msg'] = f"目标文件 {tag_file_name} 文件类型 {content_type} 上传成功"
self.back_dict['download_url'] = download_url
return self.back_dict
except MinioException as err:
self.back_dict['result'] = False
self.back_dict['msg'] = f"目标文件 {tag_file_name} 文件类型 {content_type} 上传失败"
self.back_dict['error'] = err
return self.back_dict
# 获取对象的元数据
def re_stat_object(self, tag_bucket_name=None, tag_file_name=None):
'''
:param tag_bucket_name: 目标存储桶
:param tag_file_name: 当前存储文件在存储桶的文件名
:return:
'''
tag_bucket_name = self.get_tag_bucket_name(tag_bucket_name)
try:
stat = self.minioClient.stat_object(tag_bucket_name, tag_file_name)
self.back_dict['msg'] = f"目标文件 {tag_file_name} 元数据获取成功"
self.back_dict['stat'] = stat
return self.back_dict
except MinioException as err:
self.back_dict['result'] = False
self.back_dict['msg'] = f"目标文件 {tag_file_name} 元数据获取失败"
self.back_dict['error'] = err
return self.back_dict
# 删除对象
def remove_object(self, tag_file_name=None, tag_bucket_name=None):
tag_bucket_name = self.get_tag_bucket_name(tag_bucket_name)
try:
res = self.minioClient.remove_object(tag_bucket_name, tag_file_name)
self.back_dict['msg'] = f"目标对象 {tag_file_name} 删除成功"
return self.back_dict
except MinioException as err:
self.back_dict['result'] = False
self.back_dict['msg'] = f"目标对象 {tag_file_name} 删除失败"
self.back_dict['error'] = err
return self.back_dict
# 删除存储桶中的多个对象
def remove_objects(self, tag_bucket_name=None, tag_file_name_list=None):
tag_bucket_name = self.get_tag_bucket_name(tag_bucket_name)
try:
# tag_file_name_list = ['1.txt', '2.txt', '3.txt']
delete_object_list = []
for tag_file_name in tag_file_name_list:
delete_object_list.append(DeleteObject(tag_file_name))
for del_err in self.minioClient.remove_objects(tag_bucket_name, delete_object_list):
msg = f"目标桶 {tag_bucket_name} 目标文件 {del_err} 删除成功 " # 源码里面会打印东西,但是我这里没法印出来,没搞懂
print(msg)
self.back_dict['msg'] = f"目标对象列表 {tag_file_name_list} 删除成功"
return self.back_dict
except MinioException as err:
self.back_dict['result'] = False
self.back_dict['msg'] = f"目标对象列表 {tag_file_name_list} 删除失败"
self.back_dict['error'] = err
return self.back_dict
# 删除一个未完整上传的对象(失败)
def remove_incomplete_upload(self, tag_bucket_name=None, tag_file_name=None):
# 没有这个方法
# 主动创建桶 tag_bucket_name 有值
if tag_bucket_name:
tag_bucket_name = tag_bucket_name
else:
tag_bucket_name = self.bucket_name
try:
self.minioClient.remove_incomplete_upload(tag_bucket_name, tag_file_name)
msg = f"目标桶 {tag_bucket_name} 目标文件 {tag_file_name} 删除成功 "
print(msg)
except MinioException as err:
msg = f"目标桶 {tag_bucket_name} 目标文件 {tag_file_name} 删除失败 失败原因 {err}"
print(msg)
if __name__ == '__main__':
...
【四】存储桶相关说明
【1】初始化存储桶
(1)参数
参数名称 |
参数类型 |
注释 |
来源 |
权重 |
endpoint |
字符串 |
endpoint指定的是你Minio的远程IP及端口 |
settings.ENDPOINT |
必填参数 |
access_key |
字符串 |
accesskey指定的是你的Minio服务器访问key |
settings.ACCESS_KEY |
必填参数 |
secret_key |
字符串 |
secret_key指定的是你登录时需要用的key,类似密码 |
settings.SECRET_KEY |
必填参数 |
bucket_name |
字符串 |
必须指定一个默认存储桶名称 |
settings.BUCKET_NAME |
必填参数 |
secure |
字符串 |
secure指定是否以安全模式创建Minio连接,建议为False |
settings.SECURE |
必填参数 |
(2)实现
# 创建连接桶对象 __init__(self, endpoint, access_key, secret_key, bucket_name, secure=False)
bucket = BucketOperation(endpoint=settings.ENDPOINT, access_key=settings.ACCESS_KEY, secret_key=settings.SECRET_KEY,
bucket_name=settings.BUCKET_NAME, secure=settings.SECURE)
(3)结果
【2】检查桶(默认不创建)
(1)参数
参数名称 |
参数类型 |
注释 |
权重 |
tag_bucket_name |
字符串 |
存储桶名称 |
非必传参数 |
(2)实现
# 检查桶,默认不创建 -- create_bucket(self, tag_bucket_name=None)
bucket.create_bucket()
(3)结果
{'result': True, 'tag_bucket_name': None, 'msg': '目标存储桶 testbucket 已经存在', 'msg_list': []}
【3】创建桶(主动创建新桶)
(1)参数
参数名称 |
参数类型 |
注释 |
权重 |
tag_bucket_name |
字符串 |
存储桶名称 |
必传参数 |
(2)实现
# 创建桶,主动创建 -- create_bucket(self, tag_bucket_name=None)
tag_bucket_name = 'test5'
bucket.create_bucket(tag_bucket_name=tag_bucket_name)
(3)结果
{'result': True, 'tag_bucket_name': 'test5', 'msg': '目标存储桶 test5 创建成功', 'msg_list': []}
【4】获取所有桶列表
(1)参数
参数名称 |
参数类型 |
注释 |
权重 |
tag_bucket_name |
字符串 |
存储桶名称 |
可选参数 |
(2)实现
# 获取所有桶列表 -- get_bucket_list(self, tag_bucket_name=None)
bucket.get_bucket_list()
(3)结果
{'result': True, 'tag_bucket_name': None, 'msg': '存储桶列表获取成功', 'msg_list': [
{'bucket_name': 'test1', 'bucket_create_time_utc': '2023-08-12 08:55:10','bucket_create_time_sh': '2023-08-12 16:55:10'},
{'bucket_name': 'test2', 'bucket_create_time_utc': '2023-08-12 13:19:30','bucket_create_time_sh': '2023-08-12 21:19:30'},
{'bucket_name': 'test4', 'bucket_create_time_utc': '2023-08-13 03:19:34','bucket_create_time_sh': '2023-08-13 11:19:34'},
{'bucket_name': 'test5', 'bucket_create_time_utc': '2023-08-13 03:19:57','bucket_create_time_sh': '2023-08-13 11:19:57'},
{'bucket_name': 'testbucket', 'bucket_create_time_utc': '2023-08-12 05:18:30','bucket_create_time_sh': '2023-08-12 13:18:30'}
]}
【5】指定存储桶访问
(1)参数
参数名称 |
参数类型 |
注释 |
权重 |
tag_bucket_name |
字符串 |
存储桶名称 |
可选参数 |
(2)实现
# 指定存储桶访问 -- get_bucket_list(self, tag_bucket_name=None)
tag_bucket_name = 'test1'
bucket.get_bucket_list(tag_bucket_name=tag_bucket_name)
(3)结果
{'result': True, 'tag_bucket_name': 'test1', 'msg': '存储桶列表获取成功', 'msg_list': [
{'bucket_name': 'test1', 'bucket_create_time_utc': '2023-08-12 08:55:10','bucket_create_time_sh': '2023-08-12 16:55:10'},
{'bucket_name': 'test2', 'bucket_create_time_utc': '2023-08-12 13:19:30','bucket_create_time_sh': '2023-08-12 21:19:30'},
{'bucket_name': 'test4', 'bucket_create_time_utc': '2023-08-13 03:19:34','bucket_create_time_sh': '2023-08-13 11:19:34'},
{'bucket_name': 'test5', 'bucket_create_time_utc': '2023-08-13 03:19:57','bucket_create_time_sh': '2023-08-13 11:19:57'},
{'bucket_name': 'testbucket', 'bucket_create_time_utc': '2023-08-12 05:18:30','bucket_create_time_sh': '2023-08-12 13:18:30'}
]}
【6】删除指定桶
(1)参数
参数名称 |
参数类型 |
注释 |
权重 |
tag_bucket_name |
字符串 |
存储桶名称 |
必传参数 |
(2)实现
# 删除指定桶 -- get_remove_bucket(self, tag_bucket_name=None)
tag_bucket_name = 'test5'
bucket.get_remove_bucket(tag_bucket_name=tag_bucket_name)
(3)结果
【7】列出目标存储桶中所有对象
(1)参数
参数名称 |
参数类型 |
注释 |
权重 |
tag_bucket_name |
字符串 |
存储桶名称 |
选传参数(不传则是默认存储桶) |
(2)实现
# 列出目标存储桶中所有对象 -- get_bucket_files(self, tag_bucket_name)
bucket.get_bucket_files()
tag_bucket_name = 'test2'
bucket.get_bucket_files(tag_bucket_name=tag_bucket_name)
(3)结果
{'result': True, 'tag_bucket_name': None, 'msg': '目标存储桶 testbucket 获取所有对象成功', 'msg_list':
[{'obj_bucket_name': 'testbucket', 'obj_name': '驿站.png', 'last_modified_utc': '2023-08-13 03:52:26',
'last_modified_sh': '2023-08-13 11:52:26', 'etag': '09ecc593ce0d0228a9657a85863ed0be', 'size': 6522,
'content_type': None},
{'obj_bucket_name': 'testbucket', 'obj_name': '驿站.png', 'last_modified_utc': '2023-08-13 03:52:26',
'last_modified_sh': '2023-08-13 11:52:26', 'etag': '09ecc593ce0d0228a9657a85863ed0be', 'size': 6522,
'content_type': None},
{'obj_bucket_name': 'testbucket', 'obj_name': '驿站.png', 'last_modified_utc': '2023-08-13 03:52:26',
'last_modified_sh': '2023-08-13 11:52:26', 'etag': '09ecc593ce0d0228a9657a85863ed0be', 'size': 6522,
'content_type': None},
{'obj_bucket_name': 'testbucket', 'obj_name': '驿站.png', 'last_modified_utc': '2023-08-13 03:52:26',
'last_modified_sh': '2023-08-13 11:52:26', 'etag': '09ecc593ce0d0228a9657a85863ed0be', 'size': 6522,
'content_type': None}
]}
{'result': True, 'tag_bucket_name': 'test2', 'msg': '目标存储桶 test2 获取所有对象成功', 'msg_list':
[{'obj_bucket_name': 'test2', 'obj_name': '2222.png', 'last_modified_utc': '2023-08-12 14:07:20',
'last_modified_sh': '2023-08-12 22:07:20', 'etag': '7603d74c4e836fde0cdf895c172ad7fb', 'size': 20912,
'content_type': None},
{'obj_bucket_name': 'test2', 'obj_name': '2222.png', 'last_modified_utc': '2023-08-12 14:07:20',
'last_modified_sh': '2023-08-12 22:07:20', 'etag': '7603d74c4e836fde0cdf895c172ad7fb', 'size': 20912,
'content_type': None}
]}
【8】列出存储桶中未完整上传的对象(失败)
(1)参数
参数名称 |
参数类型 |
注释 |
权重 |
tag_bucket_name |
字符串 |
存储桶名称 |
选传参数(不传则是默认存储桶) |
(2)实现
# 列出存储桶中未完整上传的对象(废除) -- get_list_incomplete_uploads(self, tag_bucket_name=None)
tag_bucket_name = 'test5'
bucket.get_list_incomplete_uploads(tag_bucket_name=tag_bucket_name)
(3)结果
【9】给指定的存储桶设置存储桶策略
(1)参数
参数名称 |
参数类型 |
注释 |
权重 |
tag_bucket_name |
字符串 |
存储桶名称 |
选传参数(不传则是默认存储桶) |
policy |
字符串 |
存储桶策略 |
必传参数 |
(2)实现
policy = """
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::123456789012:user/Alice"
},
"Action": [
"s3:GetObject",
"s3:PutObject"
],
"Resource": "arn:aws:s3:::test1/*"
}
]
}
"""
# 给指定的存储桶设置存储桶策略 -- get_set_bucket_policy(self, tag_bucket_name, policy)
policy = """
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::123456789012:user/Alice"
},
"Action": [
"s3:GetObject",
"s3:PutObject"
],
"Resource": "arn:aws:s3:::test1/*"
}
]
}
"""
tag_bucket_name = 'test2'
bucket.get_set_bucket_policy(tag_bucket_name=tag_bucket_name, policy=policy)
(3)结果
{'result': True, 'tag_bucket_name': 'test1', 'msg': '目标存储桶 存储策略 设置成功', 'msg_list': []}
{'result': False, 'tag_bucket_name': 'test2', 'msg': '目标存储桶 test2 设置存储策略失败', 'msg_list': [], 'error': S3Error('S3 operation failed; code: MalformedPolicy, message: bucket name does not match, resource: /test2, request_id: 177AD5BFADE2D9ED, host_id: 901192593c8d4aebefcd5e1ffb207b1846522d03b1e9cb2132c2770ef491581c, bucket_name: test2')}
【10】获取存储桶的当前策略
(1)参数
参数名称 |
参数类型 |
注释 |
权重 |
tag_bucket_name |
字符串 |
存储桶名称 |
选传参数(不传则是默认存储桶) |
(2)实现
# 获取存储桶的当前策略 -- bucket_policy(self, tag_bucket_name=None)
tag_bucket_name = 'test1'
bucket.bucket_policy(tag_bucket_name=tag_bucket_name)
(3)结果
{'result': True, 'tag_bucket_name': 'test1', 'msg': '目标存储桶 test1 获取存储策略成功', 'msg_list': [], 'policy': '{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Principal":{"AWS":["arn:aws:iam::123456789012:user/Alice"]},"Action":["s3:PutObject","s3:GetObject"],"Resource":["arn:aws:s3:::test1/*"]}]}'}
{'result': False, 'tag_bucket_name': 'test2', 'msg': '目标存储桶 test2 获取存储策略失败', 'msg_list': [], 'error': S3Error('S3 operation failed; code: NoSuchBucketPolicy, message: The bucket policy does not exist, resource: /test2, request_id: 177AD5F177D00E9A, host_id: 901192593c8d4aebefcd5e1ffb207b1846522d03b1e9cb2132c2770ef491581c, bucket_name: test2')}
【11】获取存储桶的通知配置
(1)参数
参数名称 |
参数类型 |
注释 |
权重 |
tag_bucket_name |
字符串 |
存储桶名称 |
选传参数(不传则是默认存储桶) |
(2)实现
# 获取存储桶的通知配置 -- get_bucket_notification(self, tag_bucket_name=None)
tag_bucket_name = 'test1'
bucket.get_bucket_notification(tag_bucket_name=tag_bucket_name)
(3)结果
{'result': True, 'tag_bucket_name': 'test1', 'msg': '目标存储桶 test1 通知配置 获取成功', 'msg_list': [], 'notification': <minio.notificationconfig.NotificationConfig object at 0x00000253A47F3A60>}
【12】设置存储桶的通知配置(失败)
(1)参数
参数名称 |
参数类型 |
注释 |
权重 |
tag_bucket_name |
字符串 |
存储桶名称 |
选传参数(不传则是默认存储桶) |
notification_config |
NotificationConfig类型 |
通知配置 |
必传参数 |
(2)实现
# 设置存储桶的通知配置 -- re_set_bucket_notification(self, notification_config, tag_bucket_name=None)
config = NotificationConfig(
queue_config_list=[
QueueConfig(
"QUEUE-ARN-OF-THIS-BUCKET",
["s3:ObjectCreated:*"],
config_id="1",
prefix_filter_rule=PrefixFilterRule("abc"),
),
],
)
tag_bucket_name = 'test1'
bucket.re_set_bucket_notification(tag_bucket_name=tag_bucket_name,notification_config=config)
(3)结果
{'result': False, 'tag_bucket_name': 'test1', 'msg': '目标存储桶 test1 通知配置 设置失败', 'msg_list': [], 'error': S3Error('S3 operation failed; code: InvalidArgument, message: A specified destination ARN does not exist or is not well-formed. Verify the destination ARN., resource: /test1, request_id: 177AD65BCF1969A7, host_id: 901192593c8d4aebefcd5e1ffb207b1846522d03b1e9cb2132c2770ef491581c, bucket_name: test1'), 'notification_config': <minio.notificationconfig.NotificationConfig object at 0x000001DB32814460>}
【13】移除存储桶上的所有通知配置
(1)参数
参数名称 |
参数类型 |
注释 |
权重 |
tag_bucket_name |
字符串 |
存储桶名称 |
选传参数(不传则是默认存储桶) |
(2)实现
# 移除存储桶上的所有通知 -- re_remove_all_bucket_notifications(self, tag_bucket_name=None)
tag_bucket_name = 'test1'
bucket.re_remove_all_bucket_notifications(tag_bucket_name=tag_bucket_name)
(3)结果
{'result': True, 'tag_bucket_name': 'test1', 'msg': '目标存储桶 test1 通知配置 移除成功', 'msg_list': []}
【14】监听存储桶的通知
(1)参数
参数名称 |
参数类型 |
注释 |
权重 |
tag_bucket_name |
字符串 |
存储桶名称 |
选传参数(不传则是默认存储桶) |
prefix |
字符串 |
对象前缀,用于匹配以指定前缀开头的对象。可选参数,默认为空字符串。 |
可选参数 |
suffix |
字符串 |
对象后缀,用于匹配以指定后缀结尾的对象。可选参数,默认为空字符串。 |
可选参数 |
events |
字符串/元祖 |
需要监听的事件类型。可选参数,默认为s3:ObjectCreated:* 、s3:ObjectRemoved:* 、s3:ObjectAccessed:* 三种事件类型。 |
可选参数 |
(2)实现
# 监听存储桶的通知 -- listen_bucket_notification(self, prefix, suffix, events, tag_bucket_name=None)
prefix = 'documents/'
suffix = '.pdf'
events = ('s3:ObjectCreated:*',
's3:ObjectRemoved:*',
's3:ObjectAccessed:*')
tag_bucket_name = 'test1'
bucket.listen_bucket_notification(tag_bucket_name=tag_bucket_name, prefix=prefix, suffix=suffix, events=events)
(3)结果
【五】文件操作
【1】初始化文件操作对象
(1)参数
参数名称 |
参数类型 |
注释 |
权重 |
bucket |
bucket对象 |
已经初始化的bucket对象 |
必传参数 |
(2)实现
# 创建文件操作对象 -- __init__(self, bucket_obj)
file = FileOperation(bucket)
(3)结果
【2】从桶中下载一个对象(下载文件)
- get_object 也是一种获取对象的方法,用于从内存或缓存中获取对象数据。
- 典型的应用场景是通过缓存机制将对象数据缓存在内存中,提高读取性能。
- 对于频繁需要读取的对象数据,可以使用 get_object 方法从缓存中快速获取,减少对底层数据源的访问。
- get_object 方法一般直接从内存或缓存中获取对象,不涉及底层数据源的访问。
(1)参数
参数名称 |
参数类型 |
注释 |
权重 |
tag_bucket_name |
字符串 |
存储桶名称 |
选传参数(不传则是默认存储桶) |
save_file_path |
字符串 |
保存文件的路径 |
必传参数 |
tag_file_name |
字符串 |
桶中存在的文件名称 |
必传参数 |
start |
数字 |
区间起始位置 |
默认是0(下载完成文件) |
end |
字符串 |
区间结束位置 |
默认是0(下载完成文件) |
(2)实现
# 从桶中下载一个对象(支持txt、csv文件)并保存到指定路径 -- load_object(self, save_file_path, tag_file_name, tag_bucket_name=None, start=0, end=0)
save_file_path = r'E:\Old Boy\luffy\luffyCity\luffyCity\libs\MinioPySdk'
tag_file_name = '4.png'
# tag_file_name = '02.json'
tag_bucket_name = 'test1'
file.load_object(save_file_path=save_file_path,tag_file_name=tag_file_name,tag_bucket_name=tag_bucket_name)
(3)结果
{'result': True, 'tag_bucket_name': 'test1', 'msg': '目标文件 02.json 下载成功', 'msg_list': []}
{'result': True, 'tag_bucket_name': 'test1', 'msg': '目标文件 4.png 下载成功', 'msg_list': []}
【3】下载并将文件保存到本地(下载文件)
- fget_object 是一种获取对象的方法,用于从某个数据源或存储系统中获取对象数据。
- 典型的应用场景是从数据库、文件系统或网络资源中获取对象的数据。
- 通常需要提供参数来指定数据源、路径或关键字等,以便获取特定的对象数据。
- fget_object 方法一般会封装访问数据源的底层逻辑,如打开文件、查询数据库等。
(1)参数
参数名称 |
参数类型 |
注释 |
权重 |
tag_bucket_name |
字符串 |
存储桶名称 |
选传参数(不传则是默认存储桶) |
save_file_path |
字符串 |
保存文件的路径 |
必传参数 |
tag_file_name |
字符串 |
桶中存在的文件名称 |
必传参数 |
(2)实现
# 下载并将文件保存到本地 -- fget_object(self, save_file_path, tag_file_name, tag_bucket_name=None)
save_file_path = r'E:\Old Boy\luffy\luffyCity\luffyCity\libs\MinioPySdk'
tag_file_name = '4.png'
tag_bucket_name = 'test1'
file.fget_object(save_file_path=save_file_path, tag_file_name=tag_file_name, tag_bucket_name=tag_bucket_name)
(3)结果
{'result': True, 'tag_bucket_name': 'test1', 'msg': '目标文件下载成功', 'msg_list': [], 'addr': 'E:\\Old Boy\\luffy\\luffyCity\\luffyCity\\libs\\MinioPySdk\\4.png'}
【4】拷贝对象存储服务上的源对象到一个新对象(复制文件)
(1)参数
参数名称 |
参数类型 |
注释 |
权重 |
start_file_name |
字符串 |
源文件桶的文件名字 |
必填(不填就是默认桶中存在的文件) |
start_bucket_name |
字符串 |
源文件桶对象 |
必填(不填就是默认桶) |
end_file_name |
字符串 |
目标对象桶的文件名字 |
必填 |
end_bucket_name |
字符串 |
目标桶对象 |
必填 |
(2)实现
# 拷贝对象存储服务上的源对象到一个新对象 -- get_copy_object(self, start_file_name, end_file_name=None, start_bucket_name=None, end_bucket_name=None)
start_bucket_name = 'test4'
start_file_name = '我的.png'
end_bucket_name = 'test2'
end_file_name = '我的test2.png'
file.get_copy_object(start_bucket_name=start_bucket_name, start_file_name=start_file_name,
end_bucket_name=end_bucket_name, end_file_name=end_file_name)
(3)结果
{'result': True, 'tag_bucket_name': 'test2', 'msg': '源桶 :>> test4 源文件 :>> 我的.png 目标桶 :>> test2 目标文件 :>> 我的test2.png 拷贝成功', 'msg_list': [], 'copy_result': <minio.helpers.ObjectWriteResult object at 0x000001A27A2124F0>}
【5】添加一个新的对象到对象存储服务(上传文件)
- put_object是另一种常见的上传文件方法,通常用于单个小文件或者网络非常稳定的情况。
- 使用put_object方法时,会将整个文件一次性上传到云端存储空间。
- 如果在上传过程中网络连接中断,put_object方法无法自动恢复上传,需要重新启动上传过程。
- 对于小文件或网络稳定的情况,使用put_object方法可以简单方便地将文件上传到云端存储空间。
(1)参数
参数名称 |
参数类型 |
注释 |
权重 |
upload_file_path |
字符串 |
本地上传文件的路径 |
必填(不填就是默认桶中存在的文件) |
tag_bucket_name |
字符串 |
目标存储桶 |
必填(不填就是默认桶) |
tag_file_name |
字符串 |
当前存储文件在存储桶的文件名 |
必填 |
content_type |
字符串 |
存储文件的类型(可根据需要选择) 指定上传的数据类型 "application/json"、"image/jpeg"、"text/plain"等。 |
可选 |
(2)实现
# 添加一个新的对象到对象存储服务 -- upload_object(self, upload_file_path, tag_bucket_name=None, tag_file_name=None, content_type=None)
upload_file_path = r'E:\Old Boy\luffy\luffyCity\luffyCity\libs\MinioPySdk\4.png'
tag_bucket_name = 'test2'
tag_file_name = '4.png'
content_type = ''
file.upload_object(upload_file_path=upload_file_path, tag_bucket_name=tag_bucket_name,
tag_file_name=tag_file_name)
(3)结果
{'result': True, 'tag_bucket_name': 'test2', 'msg': '目标桶 test2 目标文件 4.png 上传成功', 'msg_list': [], 'download_url': 'http://43.138.48.158:9011/test2/4.png?x-amz-server-side-encryption=AES256&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=7FGId3bewvgBq75Upf0Q%2F20230813%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20230813T065837Z&X-Amz-Expires=604800&X-Amz-SignedHeaders=host&X-Amz-Signature=86aaad300db93f2a90abd05c25245f9031c15e787cdacf9d47d93bf953a46e9f'}
【6】通过文件上传到对象中(上传文件)
- fput_object是芝浩科技开发的一种对象存储SDK提供的功能,其主要特点是支持断点续传。
- 在使用fput_object方法时,可以将待上传的文件拆分成多个分片进行传输,以实现在网络不稳定的情况下,更可靠地上传大文件。
- 如果上传过程中网络连接中断,fput_object方法可以自动寻找中断点,并从中断处继续上传,而无需重新上传整个文件。
- 使用fput_object方法需要在SDK中配置分片大小、分片重试次数等参数。
- 对于较大的文件,特别是在网络环境不稳定的情况下,建议使用fput_object方法进行上传,以实现断点续传,保证文件上传的可靠性和稳定性。
(1)参数
参数名称 |
参数类型 |
注释 |
权重 |
upload_file_path |
字符串 |
本地上传文件的路径 |
必填(不填就是默认桶中存在的文件) |
tag_bucket_name |
字符串 |
目标存储桶 |
必填(不填就是默认桶) |
tag_file_name |
字符串 |
当前存储文件在存储桶的文件名 |
必填 |
content_type |
字符串 |
存储文件的类型(可根据需要选择) 指定上传的数据类型 "application/json"、"image/jpeg"、"text/plain"等。 |
可选 |
(2)实现
# 通过文件上传到对象中 -- fput_object(self, tag_file_name=None, tag_bucket_name=None, upload_file_path=None, content_type=None)
upload_file_path = r'E:\Old Boy\luffy\luffyCity\luffyCity\libs\MinioPySdk\4.png'
tag_bucket_name = 'test2'
tag_file_name = '4.png'
content_type = ''
file.upload_object(upload_file_path=upload_file_path, tag_bucket_name=tag_bucket_name,
tag_file_name=tag_file_name)
(3)结果
{'result': True, 'tag_bucket_name': 'test2', 'msg': '目标桶 test2 目标文件 4.png 上传成功', 'msg_list': [], 'download_url': 'http://43.138.48.158:9011/test2/4.png?x-amz-server-side-encryption=AES256&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=7FGId3bewvgBq75Upf0Q%2F20230813%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20230813T065837Z&X-Amz-Expires=604800&X-Amz-SignedHeaders=host&X-Amz-Signature=86aaad300db93f2a90abd05c25245f9031c15e787cdacf9d47d93bf953a46e9f'}
【7】获取对象的元数据
(1)参数
参数名称 |
参数类型 |
注释 |
权重 |
tag_bucket_name |
字符串 |
目标存储桶 |
必填(不填就是默认桶) |
tag_file_name |
字符串 |
当前存储文件在存储桶的文件名 |
必填 |
(2)实现
# 获取对象的元数据 -- re_stat_object(self, tag_bucket_name=None, tag_file_name=None)
tag_bucket_name = 'test2'
tag_file_name = '4.png'
file.re_stat_object( tag_bucket_name=tag_bucket_name,tag_file_name=tag_file_name)
(3)结果
{'result': True, 'tag_bucket_name': 'test2', 'msg': '目标文件 4.png 元数据获取成功', 'msg_list': [], 'stat': <minio.datatypes.Object object at 0x000001B8572023D0>}
【8】删除存储桶中的对象(单个)
(1)参数
参数名称 |
参数类型 |
注释 |
权重 |
tag_bucket_name |
字符串 |
目标存储桶 |
必填(不填就是默认桶) |
tag_file_name |
字符串 |
当前存储文件在存储桶的文件名 |
必填 |
(2)实现
# 删除对象 -- remove_object(self, tag_file_name=None, tag_bucket_name=None)
tag_bucket_name = 'test2'
tag_file_name = '4.png'
file.remove_object(tag_bucket_name=tag_bucket_name, tag_file_name=tag_file_name)
(3)结果
{'result': True, 'tag_bucket_name': 'test2', 'msg': '目标对象 4.png 删除成功', 'msg_list': []}
【9】删除存储桶中的多个对象(多个)
(1)参数
参数名称 |
参数类型 |
注释 |
权重 |
tag_bucket_name |
字符串 |
目标存储桶 |
必填(不填就是默认桶中存在的文件) |
tag_file_name_list |
列表 |
当前存储文件在存储桶的文件名列表 |
必填 |
(2)实现
# 删除存储桶中的多个对象 -- remove_objects(self, tag_bucket_name=None, tag_file_name_list=None)
tag_bucket_name = 'test2'
tag_file_name_list = ['1.png', '2.png', '3.png']
file.remove_objects(tag_bucket_name=tag_bucket_name, tag_file_name_list=tag_file_name_list)
(3)结果
{'result': True, 'tag_bucket_name': 'test2', 'msg': "目标对象列表 ['1.png', '2.png', '3.png'] 删除成功", 'msg_list': []}
【4】删除一个未完整上传的对象(失败)
(1)参数
(2)实现
(3)结果