下载mc

windows
地址:https://dl.minio.org.cn/client/mc/release/windows-amd64/mc.exe

基本使用

通过双击执行文件,或者 在命令 提示符或PowerShell中运行以下内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 查看所有命令的帮助
\path\to\mc.exe --help
#给minio服务器设置一个别名,填入地址、账号和密码进行连接。需要注意的是端口要用api的端口
mc alias set nickname url username password
# 删除服务器
mc alias remove nickname
# 查看所有的 alias
mc alias ls
# 查看bucket里面的内容
mc ls nickname
# 下载单个文件到本地
mc cp nickname/bucketName/1715759535550.jpg E:\download
# 批量下载文件到本地
## 递归下载整个目录
mc cp --recursive nickname/bucketName/ E:\download
## 使用通配符下载匹配文件
mc cp nickname/bucketName/*.jpg E:\download
# 排除特定的文件
mc cp --exclude "*.tmp" nickname/bucketName/ ./clean_data/

多线程加速

没效果!!!!!!!!做个记录
windows

1
2
3
4
5
6
7
8
9
10
 # 启用多线程(默认4线程)
set MC_ENABLE_PARALLEL=true
# 手动设置线程数
set MC_PARALLEL_THREADS=8
# 检查是否设置成功
echo %MC_ENABLE_PARALLEL%
# 开始导出
mc cp --recursive nickname/bucketName/ E:\download
# 可以加入 --debug 查看详情
mc cp --debug --recursive nickname/bucketName/ E:\download

java 调用 mc 案例

MinioProperties

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

public class MinioProperties {

public static boolean hasMinio = true;

/**
* 对象存储服务的URL
*/
// public static String endpoint = "http://10.100.50.217:9002";
public static String endpoint = "http://10.100.50.67:9000";

/**
* Access key 账户ID
*/
public static String accessKey = "minioadmin";

/**
* Secret key 密码
*/
public static String secretKey = "minioadmin";

/**
* 默认的存储桶名称
*/
public static String bucket = "windit";

public static String aliasName = "aliasWindIT";

}

MinioManager

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.LogManager;

import java.io.*;
import java.net.URL;
import java.net.URLDecoder;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;

/**
* @author xuy
*/
public class MinioManager {
public static final org.apache.logging.log4j.Logger LOG = LogManager.getLogger(MinioManager.class);
private static final String WIN = "win";
private static final String SUCCESS = "successfully";
/**
* mc客户端路径配置
*/
private static final String MC_PATH;
private static final String FIRST;
private static final String SECOND;
private static final String THREE;
/**
* 调用的 cmd 进程列表
*/
private static final List<Process> PROCESS_LIST = new ArrayList<Process>();

static {
String os = System.getProperty("os.name").toLowerCase();

URL url = MinioManager.class.getProtectionDomain().getCodeSource().getLocation();
String filePath = null;
try {
filePath = URLDecoder.decode(url.getPath(), "utf-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
if (filePath == null) {
LOG.error("mc获取路径失败");
throw new RuntimeException("mc获取路径失败");
}
if (os.contains(WIN)) {
FIRST = "cmd";
SECOND = "/c";
THREE = "taskkill /f /t /im mc.exe";
MC_PATH = filePath.substring(1) + "minio" + File.separator + "mc.exe";
} else {
FIRST = "/bin/sh";
SECOND = "-c";
THREE = "pkill -9 mc";
MC_PATH = filePath + "minio" + File.separator + "mc";
}

}

/**
* 创建 minio 别名
*
* @return void
* @author xuy
* @date 2025/4/22 16:03
*/
public static boolean createAlias() {
String[] command = {
FIRST,
SECOND,
MC_PATH + " alias set " + MinioProperties.aliasName + " " + MinioProperties.endpoint + " " + MinioProperties.accessKey + " " + MinioProperties.secretKey
};
String result = execCommand(command, true);
return result.contains(SUCCESS);
}

/**
* Check if alias exists
*
* @return boolean
* @author xuy
* @date 2025/4/22 16:58
*/
public static boolean isAlias() {
String[] command = {
FIRST,
SECOND,
MC_PATH + " ls " + MinioProperties.aliasName
};
String result = execCommand(command, true);
if (StringUtils.isBlank(result)) {
LOG.info("不存在 alias");
return false;
}
return result.contains(MinioProperties.bucket);
}

public static boolean resetAlias() {
if (isAlias()) {
String[] command = {
FIRST,
SECOND,
MC_PATH + " alias remove " + MinioProperties.aliasName
};
String result = execCommand(command, true);
LOG.info(result.contains(SUCCESS) ? "已移除原有的 alias" : "移除原有的 alias 失败");
}
return createAlias();
}

private static String printStream(InputStream inputStream) throws IOException {
try (BufferedReader reader = new BufferedReader(
new InputStreamReader(inputStream))) {
String line;
StringBuilder sb = new StringBuilder();
while ((line = reader.readLine()) != null) {
LOG.info(line);
sb.append(line);
}
return sb.toString();
}
}

public static void destroy() {
try {
// Windows: 终止进程树
Runtime.getRuntime().exec(THREE);
LOG.info("已手动终止mc");
} catch (IOException e) {
LOG.error(e.getMessage());
e.printStackTrace();
}
}


public static String execCommand(String[] command, boolean isLog) {
String res = null;
try {
// 执行命令
ProcessBuilder processBuilder = new ProcessBuilder(command);
Process process = processBuilder.start();
// 捕获输出流
if (isLog) {
res = printStream(process.getInputStream());
}
res += printStream(process.getErrorStream());

// 等待执行完成
int exitCode = process.waitFor();
if (exitCode != 0) {
LOG.error("command命令执行失败,退出码:{},命令 {}", exitCode, command);
}
return res;
} catch (IOException | InterruptedException e) {
LOG.error("command命令执行失败:{}", e.getMessage());
return res;
}
}

public static void copyFolder(String resourcePath, String targetPath) {
LOG.info(Thread.currentThread().getName() + ":minio 数据文件复制开始");
// 构造mc命令
String[] command = {
FIRST,
SECOND,
MC_PATH,
"cp",
"--recursive",
resourcePath,
targetPath
};
execCommand(command, true);
LOG.info(Thread.currentThread().getName() + ":minio 数据文件复制结束");
}

public static void downLoadTest(String[] args) throws InterruptedException {
if (resetAlias()) {
System.out.println("重新设置了 alias");
} else {
System.out.println("使用原有的 alias");
}
String minioPath = MinioProperties.aliasName + "/" + MinioProperties.bucket + "/";
String macPath = "wpd/1743153330102";
// String resourcePath = MinioProperties.aliasName + "/" + MinioProperties.bucket + "/" + "wpd/1743153330102/25032817153917958/202503";
String resourcePath = minioPath + macPath;
Path path = Paths.get(macPath);
String targetPath = "C:\\Users\\windit\\Desktop\\demo" + File.separator + path.getParent();


new Thread() {
@Override
public void run() {
copyFolder(resourcePath, targetPath);
}
}.start();
// Thread.sleep(10 * 1000);
// destroy();
}


public static void main(String[] args) throws InterruptedException {

if (resetAlias()) {
System.out.println("重新设置了 alias");
} else {
System.out.println("使用原有的 alias");
}

String resourcePath = "C:\\Users\\windit\\Desktop\\demo\\wpd";
String targetPath = MinioProperties.aliasName + "/" + MinioProperties.bucket;


new Thread() {
@Override
public void run() {
copyFolder(resourcePath, targetPath);
}
}.start();
// Thread.sleep(10 * 1000);
// destroy();
}
}

mc 使用中遇到的问题

客户端和服务器时间相差太大

错误如下:

1
mc: <ERROR> Unable to initialize new alias from the provided credentials. The difference between the request time and the server's time is too large.

解决方法:调整客户端和服务器的时间,尽量使其差值在15min以内

参考

https://minio.org.cn/docs/minio/linux/reference/minio-mc.html