🍬 博主介绍
👨🎓 博主介绍:大家好,我是 爪哇修行者 。一名爪哇修行路上的小道友
✨主攻领域:【Java】【后端开发】
📄专栏说明:本专栏是记录博主日常修行中遇到或学到的BUG
🎉欢迎关注:一起修行 💪共勉互助 👍一起进步 👑
🙏作者水平有限,欢迎各位大佬指点,相互学习进步!
- BUG复现
在将图片格式的文件上传至MinIO进行存储时,图片上传成功,并且在MinIO控制台能预览该图片,并且在控制台点击下载后,图片是可以正常打开的。但是无法通过9090端口加网址进行访问
- BUG分析
此时程序并未报错,客户端也是回显了一张无法显示的图片,并且数据库正常写入的了图片的地址
所以图片上传是没有问题的,最有可能出现的问题应该是在上传的过程中文件损坏了。(确实如此)
但是!但是!导致我一开始没有找出这个BUG 的原因就是,在MinIO的控制台上是能预览和下载的!!导致我第一时间就排除了文件损坏这种可能性。
考虑了是不是MinIO桶权限的问题,但是同一个桶中之前上传的的图片又没问题,所以应该不是权限的问题。
然后又考虑了是不是浏览器的问题,换了个浏览器仍然如此。
最后在MinIO中重新创了个桶(排查桶的原因),并且换了个浏览器(排查浏览器原因)用无痕模式(排除缓存原因)传了一张50kb的图片(排除图片大小的原因),并取名1.jpg(排除UUID太长的原因)
但是BUG仍然存在,最后只剩下文件损坏这一种可能了,但是又不清数是什么原因导致文件损坏了。
最后就开始了漫长的逐行找错之旅。
- 问题所在
MinIO的文件上传我是调用之前写好的工具类直接上传的(已经测试过,该工具类可正常使用)
工具类部分代码:
/**
* 上传图片文件
* @param prefix 文件前缀
* @param filename 文件名
* @param inputStream 文件流
* @return 文件全路径
*/
@Override
public String uploadImgFile(String prefix, String filename,InputStream inputStream) {
String filePath = builderFilePath(prefix, filename);
try {
PutObjectArgs putObjectArgs = PutObjectArgs.builder()
.object(filePath)
.contentType("image/jpg")
.bucket(minIOConfigProperties.getBucket()).stream(inputStream,inputStream.available(),-1)
.build();
minioClient.putObject(putObjectArgs);
StringBuilder urlPath = new StringBuilder(minIOConfigProperties.getReadPath());
urlPath.append(separator+minIOConfigProperties.getBucket());
urlPath.append(separator);
urlPath.append(filePath);
return urlPath.toString();
}catch (Exception ex){
log.error("minio put file error.",ex);
throw new RuntimeException("上传文件失败");
}
}
/**
* 上传html文件
* @param prefix 文件前缀
* @param filename 文件名
* @param inputStream 文件流
* @return 文件全路径
*/
@Override
public String uploadHtmlFile(String prefix, String filename,InputStream inputStream) {
String filePath = builderFilePath(prefix, filename);
try {
PutObjectArgs putObjectArgs = PutObjectArgs.builder()
.object(filePath)
.contentType("text/html")
.bucket(minIOConfigProperties.getBucket()).stream(inputStream,inputStream.available(),-1)
.build();
minioClient.putObject(putObjectArgs);
StringBuilder urlPath = new StringBuilder(minIOConfigProperties.getReadPath());
urlPath.append(separator+minIOConfigProperties.getBucket());
urlPath.append(separator);
urlPath.append(filePath);
return urlPath.toString();
}catch (Exception ex){
log.error("minio put file error.",ex);
ex.printStackTrace();
throw new RuntimeException("上传文件失败");
}
}
/**
* 删除文件
* @param pathUrl 文件全路径
*/
@Override
public void delete(String pathUrl) {
String key = pathUrl.replace(minIOConfigProperties.getEndpoint()+"/","");
int index = key.indexOf(separator);
String bucket = key.substring(0,index);
String filePath = key.substring(index+1);
// 删除Objects
RemoveObjectArgs removeObjectArgs = RemoveObjectArgs.builder().bucket(bucket).object(filePath).build();
try {
minioClient.removeObject(removeObjectArgs);
} catch (Exception e) {
log.error("minio remove file error. pathUrl:{}",pathUrl);
e.printStackTrace();
}
}
业务层代码
//2、上传图片到MinIO
String fileName = UUID.randomUUID().toString().replace("-",""); //用UUID生成不重复的字符串
String originalFilename =multipartFile.getOriginalFilename(); //获取图片原始名称
String postfix=originalFilename.substring(originalFilename.lastIndexOf("."));//获取文件后缀
String fileId=null;
try {
fileId =fileStorageService.uploadHtmlFile("",fileName+postfix, multipartFile.getInputStream());
log.info("图片上传MinIO成功,fileId:{}",fileId);
}catch (IOException e){
log.error("WmMaterialServiceIm图片上传MinIO失败!");
e.printStackTrace();
}
这时,导致该BUG的原因就显示出来了
fileId =fileStorageService.uploadHtmlFile("",fileName+postfix, multipartFile.getInputStream());
我调用工具类的时候是自动补全的,导致调用的是 uploadHtmlFile (此处应该调用uploadImgFile)所以我上传的图片是"text/html"而不是“image/jpg”
- 总结思考
MinIO上传文件时,即使.contentType()文件类型错误,也可能上传成功。(可能是MinIO自动识别修正了,不清楚底层)
写工具类时,相似功能时,尽量使用方法重载,因为后期调用的时候很有可能因为代码自动补全而导致调用出错。
👋👋👋BUG解决完毕!经验加一!