上传多张图片时需要在对应类中增加图像地址的数组(加上数据库不存在该字段注解),在逻辑层将多张图片的地址进行拼接一起,存入数据库。
minio工具类
package com.custhitahi.zhjc.util;
import io.minio.*;
import io.minio.http.Method;
import io.minio.messages.DeleteObject;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.PostConstruct;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
/**
* @author turnersun
* @date 2022/6/17 - 16:31
*/
@Slf4j
@PropertySource("classpath:upload.properties")
@Component
public class MinioUtil {
/** minio地址+端口号 */
@Value("${minio.url}")
private String url;
/** minio用户名 */
@Value("${minio.user}")
private String user;
/** minio密码 */
@Value("${minio.password}")
private String password;
/** 桶的名称 */
@Value("${minio.bucketName}")
private String bucketName;
/** 域名 */
@Value("${minio.domain}")
private String domain;
private static MinioClient minioClient;
/**
* 不排序
*/
public final static boolean NOT_SORT = false;
/**
* 初始化minio配置
*/
@PostConstruct
public void init() {
try {
minioClient = MinioClient.builder().endpoint(url).credentials(user,password).build();
if(!isBucketExist()){
createBucket();
}
} catch (Exception e) {
e.printStackTrace();
log.error("初始化minio配置异常: 【{ }】", e.fillInStackTrace());
}
}
/**
* 存储桶是否存在
* @return true/false
*/
@SneakyThrows
public boolean isBucketExist(){
return minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
}
/**
* 创建存储桶
*/
@SneakyThrows
public void createBucket(){
minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
}
/**
* 获取访问对象的外链地址
* @param objectName 对象名称
* @return viewUrl
*/
@SneakyThrows
public String getObjectUrl(String objectName){
String ori = minioClient.getPresignedObjectUrl(
GetPresignedObjectUrlArgs.builder()
.method(Method.GET)
.bucket(bucketName)
.object(objectName)
.build()
);
String url = ori.substring(0, ori.indexOf("?"));
return domain+url.substring(url.indexOf("9000")+5);
}
@SneakyThrows
public String getObjectUrlWithBucket(String objectName,String bucketName){
String ori = minioClient.getPresignedObjectUrl(
GetPresignedObjectUrlArgs.builder()
.method(Method.GET)
.bucket(bucketName)
.object(objectName)
.build()
);
String url = ori.substring(0, ori.indexOf("?"));
return domain+url.substring(url.indexOf("9000")+5);
}
/**
* 上传本地文件
* @param objectName 欲上传的本地文件对象的名称
* @param filePath 本地文件路径
*/
@SneakyThrows
public void uploadFile(String objectName, String filePath){
minioClient.uploadObject(
UploadObjectArgs.builder()
.bucket(bucketName)
.object(objectName)
.filename(filePath)
.build());
}
public void uploadFile(String objectName, MultipartFile file) throws Exception {
minioClient.putObject(
PutObjectArgs.builder()
.bucket(bucketName)
.object(objectName)
.contentType(file.getContentType())
.stream(file.getInputStream(), file.getSize(), -1)
.build());
}
public void uploadFile(String objectName, InputStream stream, String size) throws Exception {
minioClient.putObject(
PutObjectArgs.builder()
.bucket(bucketName)
.object(objectName)
.stream(stream, Long.parseLong(size), -1)
.build());
}
@SneakyThrows
public void uploadFileWithBucket(String bucketName,String objectName, String filePath){
minioClient.uploadObject(
UploadObjectArgs.builder()
.bucket(bucketName)
.object(objectName)
.filename(filePath)
.build());
}
/**
* 下载文件
* @param fileName 文件名
* @return 文件流
*/
@SneakyThrows(Exception.class)
public InputStream download(String fileName) {
return minioClient.getObject(
GetObjectArgs.builder()
.bucket(bucketName)
.object(fileName)
.build());
}
@SneakyThrows(Exception.class)
public InputStream downloadWithBucket(String fileName,String bucketName) {
return minioClient.getObject(
GetObjectArgs.builder()
.bucket(bucketName)
.object(fileName)
.build());
}
/**
* 删除对象
* @param objectName
* @return true/false
*/
@SneakyThrows
public boolean removeObject(String objectName){
minioClient.removeObject(
RemoveObjectArgs.builder()
.bucket(bucketName)
.object(objectName)
.build()
);
return true;
}
/**
* 批量删除对象
* @param objectNames
* @return true/false
*/
public boolean removeObjects(List<String> objectNames){
List<DeleteObject> deleteObjects = new ArrayList<>(objectNames.size());
for (String objectName : objectNames){
deleteObjects.add(new DeleteObject(objectName));
}
minioClient.removeObjects(
RemoveObjectsArgs.builder()
.bucket(bucketName)
.objects(deleteObjects)
.build()
);
return true;
}
/**
* 将分钟数转换为秒数
* @param expiry 过期时间(分钟数)
* @return expiry
*/
private static int expiryHandle(Integer expiry){
expiry = expiry * 60;
if (expiry > 604800){
return 604800;
}
return expiry;
}
static class Str2IntComparator implements Comparator<String> {
private final boolean reverseOrder; // 是否倒序
public Str2IntComparator(boolean reverseOrder) {
this.reverseOrder = reverseOrder;
}
@Override
public int compare(String arg0, String arg1) {
Integer intArg0 = Integer.parseInt(arg0.substring(arg0.indexOf("/") + 1,arg0.lastIndexOf(".")));
Integer intArg1 = Integer.parseInt(arg1.substring(arg1.indexOf("/") + 1,arg1.lastIndexOf(".")));
if(reverseOrder) {
return intArg1 - intArg0;
} else {
return intArg0 - intArg1;
}
}
}
}
控制层
@Resource
private MinioUtil minioUtil;
String objectName = "invoice/";
@RequestMapping("/uploadInvoice")
public Result uploadInvoice(MultipartRequest multipartRequest) throws Exception {
Map<String, MultipartFile> fileMap = multipartRequest.getFileMap();
String url = null;
for (Map.Entry<String, MultipartFile> entry : fileMap.entrySet()) {
MultipartFile file = entry.getValue();
String originalFileName = file.getOriginalFilename();
String mainName = FileUtil.mainName(originalFileName);//aaa
String extName = FileUtil.extName(originalFileName);//png
String fileName = System.currentTimeMillis() + "_" + mainName + "." + extName;
//将文件上传到图床
minioUtil.uploadFile(objectName + fileName, file);
url = minioUtil.getObjectUrl(objectName + fileName);
}
return ResultFactory.successWithData(url);
}
服务层
@Transactional
@Override
public int addPurchaseDetail(FireconPurchaseDetail fireconPurchaseDetail) {
int res = -1;
// 参数判空处理
if(ObjectUtil.isEmpty(fireconPurchaseDetail)) {
throw new NullPointerException();
}
try {
String result = String.join(",", fireconPurchaseDetail.getImageUrls());
fireconPurchaseDetail.setImg(result);
// 保存到数据库
fireconPurchaseDetail.setApplicationDate(LocalDateTime.now().toLocalDate());
fireconPurchaseDetail.setApplicationMoney(fireconPurchaseDetail.getApplicationPrice().multiply(fireconPurchaseDetail.getApplicationNum()));
fireconPurchaseDetailMapper.insert(fireconPurchaseDetail);
res = fireconPurchaseRequestMapper.updateTotal(fireconPurchaseDetail.getRequestId());
} catch (Exception e) {
throw e;
}
return res;
}
实体类
//接收前端传来的多张图片地址,数据库不存在该字段,后端做字符串拼接后存入img字段
@TableField(exist=false)
private String[] imageUrls;