spring-boot的項(xiàng)目中通過minio-java來連接minio進(jìn)行文件的操作,minio和Java程序都部署在內(nèi)網(wǎng)環(huán)境中,且都無法訪問互聯(lián)網(wǎng),Java程序通過內(nèi)網(wǎng)連接minio,我需要生成一個(gè)某文件的臨時(shí)訪問鏈接,而且是互聯(lián)網(wǎng)可以訪問的鏈接,目前我已經(jīng)通過一臺公網(wǎng)服務(wù)器的nginx可以將請求轉(zhuǎn)發(fā)到內(nèi)網(wǎng)的minio上,現(xiàn)在只要生成臨時(shí)鏈接則萬事俱備,但是minio-java這個(gè)包提供的生成臨時(shí)文件的方法getPresignedObjectUrl只能根據(jù)當(dāng)前的MinioClient對象生成,按照我的條件地址是內(nèi)網(wǎng)地址,且無法修改(因?yàn)殒溄舆M(jìn)行了簽名),所以要在簽名前調(diào)整鏈接中的信息才能做到自定義域名。
引入minio-java的依賴:
<dependency>
<groupId>io.minio</groupId>
<artifactId>minio</artifactId>
<version>8.5.4</version>
</dependency>
繼承MinioClient,擴(kuò)展獲取臨時(shí)鏈接函數(shù)
public class IMinioClient extends MinioClient {
private String publicBaseUrl;
public void setPublicBaseUrl(String publicBaseUrl) {
this.publicBaseUrl = publicBaseUrl;
}
protected IMinioClient(MinioClient client) {
super(client);
}
/**
* 獲取公網(wǎng)臨時(shí)訪問地址
* @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);
}
/**
* 獲取臨時(shí)訪問地址,可以指定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();
}
}
配置類
@Configuration
@ConfigurationProperties(prefix = "minio")
public class MinioConfig {
/**
* 服務(wù)地址
*/
private String url;
/**
* 用戶名
*/
private String accessKey;
/**
* 密碼
*/
private String secretKey;
/**
* 服務(wù)地址(公網(wǎng))
*/
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配置
minio:
url: http://127.0.0.1:9000
accessKey: minio
secretKey: minio
publicUrl: http://liujing.me:9000/ # 記得后面一定要加斜杠,因?yàn)槭侵苯犹鎿Q進(jìn)去的
獲取臨時(shí)訪問鏈接
@Component
public class MinioTest {
@Resource
private IMinioClient client;
/**
* 獲取指定桶中文件的臨時(shí)url (內(nèi)網(wǎng))
* @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);
}
/**
* 獲取指定桶中文件的臨時(shí)url (配置中默認(rèn)的公網(wǎng)地址)
* @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);
}
/**
* 獲取指定桶中文件的臨時(shí)url (配置中默認(rèn)的公網(wǎng)地址)
* @param bucket 桶
* @param filename 文件名稱
* @param seconds 有效期 s
* @param publicBaseUrl 自定義的公網(wǎng)地址,需以斜杠結(jié)尾 "/"
*/
@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);
}
}