大家好,笔者之前在分布式文件存储系统一文中简单的介绍了一下什么是minio。
背景
笔者在业务处理,发现前一天打印的保存的pdf图片地址打不开,所有当天保存的文件都报错:Request has expired 的错误。
<Error>
<Code>AccessDenied</Code>
<Message>Request has expired</Message>
<Key>2023-12-26/ys/9270d861050f4a1c83axxxxx.pdf</Key>
<BucketName>ys</BucketName>
<Resource>/ys/2023-12-26/ys/9270d861050f4a1c83axxxxx.pdf</Resource>
<RequestId>17A49F47F507A22S</RequestId>
<HostId>775c-1ee9-3420-4f02-b825-b8c0ba12221c</HostId>
</Error>.
因为下载 pdf 是直接访问的地址,第一时间我想的是在minio客户段存储的文件是否被删除了或者过期自动给删除了。
果然 minio 中的文件已经不存在了。
如何解决
第一时间想到的是图片过期了,通过检查源码发现,图片存入minio的时候,设置了24小时过期时间,这才导致刚刚发生图片 “集体消失” 的 Bug 。根据业务处理的需要,把过期时间设置成7天,大家可以根据实际需求设置过期时间,不建议设置永不过期,根据自己 minio 分配的内存大小来考量。
// 源码如下
//文件保存到minio
if(StringUtils.isNotEmpty(base64Str)) {
BASE64Decoder decoder = new BASE64Decoder();
byte[] fileText = decoder.decodeBuffer(base64Str);
String fileUrl = minioClient.buildFileUrl(minioClient.createFileName("pdf"));
String objectName = minioClient.createFilePath(fileUrl);
boolean upload = minioClient.putObject(objectName ,new ByteArrayInputStream(fileText));
if(upload) {
// 设置过期时间:7天
String pdfUrl = minioClient.getPresignedObjectUrl(objectName, 24 * 3600 * 7, Method.GET);
if(StringUtils.isNotEmpty(pdfUrl)) {
wrapper.lambda().set(FileInfo::getPdfUrl, pdfUrl);
}
}
}
// 持久化操作 ...
// mapper.updateFileInfo(wrapper);
建议设置一个兜底过期时间,避免误操作弄成永久有效
public String getPresignedObjectUrl(String objectName, Integer expires, Method method) {
try {
if (expires >= 1 && expires <= 604800) {
if (method == null) {
method = Method.GET;
}
return this.minioClient.getPresignedObjectUrl((GetPresignedObjectUrlArgs)((io.minio.GetPresignedObjectUrlArgs.Builder)((io.minio.GetPresignedObjectUrlArgs.Builder)GetPresignedObjectUrlArgs.builder().method(method).bucket(minioConfig.getBucket())).object(objectName)).expiry(expires, TimeUnit.SECONDS).build());
} else {
throw new InvalidExpiresRangeException(expires, "expires must be in range of 1 to 604800");
}
} catch (Throwable var6) {
// throw new Exception();
}
}