spring-boot的项目中通过minio-java来连接minio进行文件的操作,minio和Java程序都部署在内网环境中,且都无法访问互联网,Java程序通过内网连接minio,我需要生成一个某文件的临时访问链接,而且是互联网可以访问的链接,目前我已经通过一台公网服务器的nginx可以将请求转发到内网的minio上,现在只要生成临时链接则万事俱备,但是minio-java这个包提供的生成临时文件的方法getPresignedObjectUrl只能根据当前的MinioClient对象生成,按照我的条件地址是内网地址,且无法修改(因为链接进行了签名),所以要在签名前调整链接中的信息才能做到自定义域名。

引入minio-java的依赖:

1
2
3
4
5
<dependency>
<groupId>io.minio</groupId>
<artifactId>minio</artifactId>
<version>8.5.4</version>
</dependency>

继承MinioClient,扩展获取临时链接函数

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
public class IMinioClient extends MinioClient {  

private String publicBaseUrl;

public void setPublicBaseUrl(String publicBaseUrl) {
this.publicBaseUrl = publicBaseUrl;
}

protected IMinioClient(MinioClient client) {
super(client);
}

/**
* 获取公网临时访问地址
* @param args
* @return
* @throws ErrorResponseException
* @throws InsufficientDataException
* @throws InternalException
* @throws InvalidKeyException
* @throws InvalidResponseException
* @throws IOException
* @throws NoSuchAlgorithmException
* @throws XmlParserException
* @throws ServerException
*/
public String getPresignedObjectPublicUrl(GetPresignedObjectUrlArgs args) throws ServerException, InsufficientDataException, ErrorResponseException, IOException, NoSuchAlgorithmException, InvalidKeyException, InvalidResponseException, XmlParserException, InternalException {
return getPresignedObjectUrl(args, publicBaseUrl);
}

/**
* 获取临时访问地址,可以指定baseurl
* @param args
* @param endpoint
* @return
* @throws ErrorResponseException
* @throws InsufficientDataException
* @throws InternalException
* @throws InvalidKeyException
* @throws InvalidResponseException
* @throws IOException
* @throws NoSuchAlgorithmException
* @throws XmlParserException
* @throws ServerException
*/
public String getPresignedObjectUrl(GetPresignedObjectUrlArgs args, String endpoint)
throws ErrorResponseException, InsufficientDataException, InternalException,
InvalidKeyException, InvalidResponseException, IOException, NoSuchAlgorithmException,
XmlParserException, ServerException {
checkArgs(args);

byte[] body = (args.method() == Method.PUT || args.method() == Method.POST) ? EMPTY_BODY : null;

Multimap<String, String> queryParams = newMultimap(args.extraQueryParams());
if (args.versionId() != null) {
queryParams.put("versionId", args.versionId());
}

String region = getRegion(args.bucket(), args.region());
if (provider == null) {
HttpUrl url = buildUrl(args.method(), args.bucket(), args.object(), region, queryParams);
return url.toString();
}

Credentials creds = provider.fetch();
if (creds.sessionToken() != null) {
queryParams.put("X-Amz-Security-Token", creds.sessionToken());
}
HttpUrl url = buildUrl(args.method(), args.bucket(), args.object(), region, queryParams);
// 这部分修改访问地址,修改方式就是直接将baseurl替换成自定义的地址
if (endpoint != null){
url = url.newBuilder(url.toString().replace(baseUrl.toString(), endpoint)).build();
}
Request request =
createRequest(
url,
args.method(),
args.extraHeaders() == null ? null : httpHeaders(args.extraHeaders()),
body,
0,
creds);
url = Signer.presignV4(request, region, creds.accessKey(), creds.secretKey(), args.expiry());
return url.toString();
}

}

配置类

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
@Configuration  
@ConfigurationProperties(prefix = "minio")
public class MinioConfig {

/**
* 服务地址
*/
private String url;

/**
* 用户名
*/
private String accessKey;

/**
* 密码
*/
private String secretKey;

/**
* 服务地址(公网)
*/
private String publicUrl;

@Bean
public IMinioClient getMinioClient() {
MinioClient minioClient = MinioClient.builder().endpoint(url).credentials(accessKey, secretKey).build();
IMinioClient client = new IMinioClient(minioClient);
client.setPublicBaseUrl(publicUrl);
return client;
}
}

yml配置

1
2
3
4
5
minio:
url: http://127.0.0.1:9000
accessKey: minio
secretKey: minio
publicUrl: http://liujing.me:9000/ # 记得后面一定要加斜杠,因为是直接替换进去的

获取临时访问链接

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
@Component  
public class MinioTest {

@Resource
private IMinioClient client;

/**
* 获取指定桶中文件的临时url (内网)
* @param bucket 桶
* @param filename 文件名称
* @param seconds 有效期 s
*/
@SneakyThrows(Exception.class)
public String getTemporarilyUrl(String bucket, String filename, int seconds){
GetPresignedObjectUrlArgs build = GetPresignedObjectUrlArgs.builder()
.method(Method.GET)
.bucket(bucket)
.object(filename)
.expiry(seconds)
.build();
return client.getPresignedObjectUrl(build);
}

/**
* 获取指定桶中文件的临时url (配置中默认的公网地址)
* @param bucket 桶
* @param filename 文件名称
* @param seconds 有效期 s
*/
@SneakyThrows(Exception.class)
public String getPresignedObjectPublicUrl(String bucket, String filename, int seconds){
GetPresignedObjectUrlArgs build = GetPresignedObjectUrlArgs.builder()
.method(Method.GET)
.bucket(bucket)
.object(filename)
.expiry(seconds)
.build();
return client.getPresignedObjectPublicUrl(build);
}

/**
* 获取指定桶中文件的临时url (配置中默认的公网地址)
* @param bucket 桶
* @param filename 文件名称
* @param seconds 有效期 s
* @param publicBaseUrl 自定义的公网地址,需以斜杠结尾 "/"
*/
@SneakyThrows(Exception.class)
public String getPresignedObjectPublicUrl(String bucket, String filename, int seconds, String publicBaseUrl){
GetPresignedObjectUrlArgs build = GetPresignedObjectUrlArgs.builder()
.method(Method.GET)
.bucket(bucket)
.object(filename)
.expiry(seconds)
.build();
return client.getPresignedObjectUrl(build, publicBaseUrl);
}

}