spring-boot的项目中通过minio-java来连接minio进行文件的操作,minio和Java程序都部署在内网环境中,且都无法访问互联网,Java程序通过内网连接minio,我需要生成一个某文件的临时访问链接,而且是互联网可以访问的链接,目前我已经通过一台公网服务器的nginx可以将请求转发到内网的minio上,现在只要生成临时链接则万事俱备,但是minio-java这个包提供的生成临时文件的方法getPresignedObjectUrl
只能根据当前的MinioClient对象生成,按照我的条件地址是内网地址,且无法修改(因为链接进行了签名),所以要在签名前调整链接中的信息才能做到自定义域名。
引入minio-java的依赖:
<dependency>
<groupId>io.minio</groupId>
<artifactId>minio</artifactId>
<version>8.5.4</version>
</dependency>
继承MinioClient,扩展获取临时链接函数
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();
}
}
配置类
@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配置
minio:
url: http://127.0.0.1:9000
accessKey: minio
secretKey: minio
publicUrl: http://liujing.me:9000/ # 记得后面一定要加斜杠,因为是直接替换进去的
获取临时访问链接
@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);
}
}