Springboot整合minio實(shí)現(xiàn)文件服務(wù)的教程詳解
首先pom文件引入相關(guān)依賴
<!--minio-->
<dependency>
<groupId>io.minio</groupId>
<artifactId>minio</artifactId>
<version>3.0.10</version>
</dependency>springboot配置文件application.yml 里配置minio信息
#minio配置
minio:
endpoint: http://${minio_host:172.16.10.21}:9000/
accessKey: ${minio_user:minioadmin}
secretKey: ${minio_pwd:minioadmin}
bucket: ${minio_space:spacedata}
http-url: http://${minio_url:172.16.10.21}:9000/
imgSize: 10485760
fileSize: 1048576000創(chuàng)建MinioItem字段項(xiàng)目類
import io.minio.messages.Item;
import io.minio.messages.Owner;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.Date;
@Data
public class MinioItem {
/**對(duì)象名稱**/
@ApiModelProperty("對(duì)象名稱")
private String objectName;
/**最后操作時(shí)間**/
@ApiModelProperty("最后操作時(shí)間")
private Date lastModified;
private String etag;
/**對(duì)象大小**/
@ApiModelProperty("對(duì)象大小")
private String size;
private String storageClass;
private Owner owner;
/**對(duì)象類型:directory(目錄)或file(文件)**/
@ApiModelProperty("對(duì)象類型:directory(目錄)或file(文件)")
private String type;
public MinioItem(String objectName, Date lastModified, String etag, String size, String storageClass, Owner owner, String type) {
this.objectName = objectName;
this.lastModified = lastModified;
this.etag = etag;
this.size = size;
this.storageClass = storageClass;
this.owner = owner;
this.type = type;
}
public MinioItem(Item item) {
this.objectName = item.objectName();
this.type = item.isDir() ? "directory" : "file";
this.etag = item.etag();
long sizeNum = item.objectSize();
this.size = sizeNum > 0 ? convertFileSize(sizeNum):"0";
this.storageClass = item.storageClass();
this.owner = item.owner();
try {
this.lastModified = item.lastModified();
}catch(NullPointerException e){}
}
public String convertFileSize(long size) {
long kb = 1024;
long mb = kb * 1024;
long gb = mb * 1024;
if (size >= gb) {
return String.format("%.1f GB", (float) size / gb);
} else if (size >= mb) {
float f = (float) size / mb;
return String.format(f > 100 ? "%.0f MB" : "%.1f MB", f);
} else if (size >= kb) {
float f = (float) size / kb;
return String.format(f > 100 ? "%.0f KB" : "%.1f KB", f);
} else{
return String.format("%d B", size);
}
}
}創(chuàng)建MinioTemplate模板類
import com.gis.spacedata.domain.dto.minio.MinioItem;
import com.google.common.collect.Lists;
import io.minio.MinioClient;
import io.minio.ObjectStat;
import io.minio.Result;
import io.minio.errors.*;
import io.minio.messages.Bucket;
import io.minio.messages.Item;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.util.FileCopyUtils;
import org.xmlpull.v1.XmlPullParserException;
import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
@Slf4j
@Component
@RequiredArgsConstructor
public class MinioTemplate implements InitializingBean {
/**
* minio的路徑
**/
@Value("${minio.endpoint}")
private String endpoint;
/**
* minio的accessKey
**/
@Value("${minio.accessKey}")
private String accessKey;
/**
* minio的secretKey
**/
@Value("${minio.secretKey}")
private String secretKey;
/**
* 下載地址
**/
@Value("${minio.http-url}")
private String httpUrl;
@Value("${minio.bucket}")
private String bucket;
private static MinioClient minioClient;
@Override
public void afterPropertiesSet() throws Exception {
minioClient = new MinioClient(endpoint, accessKey, secretKey);
}
@SneakyThrows
public boolean bucketExists(String bucketName) {
return minioClient.bucketExists(bucketName);
}
/**
* 創(chuàng)建bucket
*
* @param bucketName bucket名稱
*/
@SneakyThrows
public void createBucket(String bucketName) {
if (!bucketExists(bucketName)) {
minioClient.makeBucket(bucketName);
}
}
/**
* 獲取全部bucket
* <p>
* https://docs.minio.io/cn/java-client-api-reference.html#listBuckets
*/
@SneakyThrows
public List<Bucket> getAllBuckets() {
return minioClient.listBuckets();
}
/**
* 根據(jù)bucketName獲取信息
*
* @param bucketName bucket名稱
*/
@SneakyThrows
public Optional<Bucket> getBucket(String bucketName) {
return minioClient.listBuckets().stream().filter(b -> b.name().equals(bucketName)).findFirst();
}
/**
* 根據(jù)bucketName刪除信息
*
* @param bucketName bucket名稱
*/
@SneakyThrows
public void removeBucket(String bucketName) {
minioClient.removeBucket(bucketName);
}
/**
* 根據(jù)文件前綴查詢文件
*
* @param bucketName bucket名稱
* @param prefix 前綴
* @param recursive 是否遞歸查詢
* @return MinioItem 列表
*/
@SneakyThrows
public List<MinioItem> getAllObjectsByPrefix(String bucketName, String prefix, boolean recursive) {
List<MinioItem> objectList = new ArrayList<>();
Iterable<Result<Item>> objectsIterator = minioClient.listObjects(bucketName, prefix, recursive);
for (Result<Item> result : objectsIterator) {
objectList.add(new MinioItem(result.get()));
}
return objectList;
}
/**
* 獲取文件外鏈
*
* @param bucketName bucket名稱
* @param objectName 文件名稱
* @param expires 過期時(shí)間 <=7
* @return url
*/
@SneakyThrows
public String getObjectURL(String bucketName, String objectName, Integer expires) {
return minioClient.presignedGetObject(bucketName, objectName, expires);
}
/**
* 獲取文件外鏈
*
* @param bucketName bucket名稱
* @param objectName 文件名稱
* @return url
*/
@SneakyThrows
public String getObjectURL(String bucketName, String objectName) {
return minioClient.presignedGetObject(bucketName, objectName);
}
/**
* 獲取文件url地址
*
* @param bucketName bucket名稱
* @param objectName 文件名稱
* @return url
*/
@SneakyThrows
public String getObjectUrl(String bucketName, String objectName) {
return minioClient.getObjectUrl(bucketName, objectName);
}
/**
* 獲取文件
*
* @param bucketName bucket名稱
* @param objectName 文件名稱
* @return 二進(jìn)制流
*/
@SneakyThrows
public InputStream getObject(String bucketName, String objectName) {
return minioClient.getObject(bucketName, objectName);
}
/**
* 上傳文件(流下載)
*
* @param bucketName bucket名稱
* @param objectName 文件名稱
* @param stream 文件流
* @throws Exception https://docs.minio.io/cn/java-client-api-reference.html#putObject
*/
public void putObject(String bucketName, String objectName, InputStream stream) throws Exception {
String contentType = "application/octet-stream";
if ("json".equals(objectName.split("\\.")[1])) {
//json格式,C++編譯生成文件,需要直接讀取
contentType = "application/json";
}
minioClient.putObject(bucketName, objectName, stream, stream.available(), contentType);
}
/**
* 上傳文件
*
* @param bucketName bucket名稱
* @param objectName 文件名稱
* @param stream 文件流
* @param size 大小
* @param contextType 類型
* @throws Exception https://docs.minio.io/cn/java-client-api-reference.html#putObject
*/
public void putObject(String bucketName, String objectName, InputStream stream, long size, String contextType) throws Exception {
minioClient.putObject(bucketName, objectName, stream, size, contextType);
}
/**
* 獲取文件信息
*
* @param bucketName bucket名稱
* @param objectName 文件名稱
* @throws Exception https://docs.minio.io/cn/java-client-api-reference.html#statObject
*/
public ObjectStat getObjectInfo(String bucketName, String objectName) throws Exception {
return minioClient.statObject(bucketName, objectName);
}
/**
* 刪除文件夾及文件
*
* @param bucketName bucket名稱
* @param objectName 文件或文件夾名稱
* @since tarzan LIU
*/
public void removeObject(String bucketName, String objectName) {
try {
if (StringUtils.isNotBlank(objectName)) {
if (objectName.endsWith(".") || objectName.endsWith("/")) {
Iterable<Result<Item>> list = minioClient.listObjects(bucketName, objectName);
list.forEach(e -> {
try {
minioClient.removeObject(bucketName, e.get().objectName());
} catch (InvalidBucketNameException invalidBucketNameException) {
invalidBucketNameException.printStackTrace();
} catch (NoSuchAlgorithmException noSuchAlgorithmException) {
noSuchAlgorithmException.printStackTrace();
} catch (InsufficientDataException insufficientDataException) {
insufficientDataException.printStackTrace();
} catch (IOException ioException) {
ioException.printStackTrace();
} catch (InvalidKeyException invalidKeyException) {
invalidKeyException.printStackTrace();
} catch (NoResponseException noResponseException) {
noResponseException.printStackTrace();
} catch (XmlPullParserException xmlPullParserException) {
xmlPullParserException.printStackTrace();
} catch (ErrorResponseException errorResponseException) {
errorResponseException.printStackTrace();
} catch (InternalException internalException) {
internalException.printStackTrace();
}
});
}
}
} catch (XmlPullParserException e) {
e.printStackTrace();
}
}
/**
* 下載文件夾內(nèi)容到指定目錄
*
* @param bucketName bucket名稱
* @param objectName 文件或文件夾名稱
* @param dirPath 指定文件夾路徑
* @since tarzan LIU
*/
public void downloadTargetDir(String bucketName, String objectName, String dirPath) {
try {
if (StringUtils.isNotBlank(objectName)) {
if (objectName.endsWith(".") || objectName.endsWith("/")) {
Iterable<Result<Item>> list = minioClient.listObjects(bucketName, objectName);
list.forEach(e -> {
try {
String url = minioClient.getObjectUrl(bucketName, e.get().objectName());
getFile(url, dirPath);
} catch (InvalidBucketNameException invalidBucketNameException) {
invalidBucketNameException.printStackTrace();
} catch (NoSuchAlgorithmException noSuchAlgorithmException) {
noSuchAlgorithmException.printStackTrace();
} catch (InsufficientDataException insufficientDataException) {
insufficientDataException.printStackTrace();
} catch (IOException ioException) {
ioException.printStackTrace();
} catch (InvalidKeyException invalidKeyException) {
invalidKeyException.printStackTrace();
} catch (NoResponseException noResponseException) {
noResponseException.printStackTrace();
} catch (XmlPullParserException xmlPullParserException) {
xmlPullParserException.printStackTrace();
} catch (ErrorResponseException errorResponseException) {
errorResponseException.printStackTrace();
} catch (InternalException internalException) {
internalException.printStackTrace();
}
});
}
}
} catch (XmlPullParserException e) {
e.printStackTrace();
}
}
public static void main(String[] args) throws
NoSuchAlgorithmException, IOException, InvalidKeyException, XmlPullParserException {
try {
// 使用MinIO服務(wù)的URL,端口,Access key和Secret key創(chuàng)建一個(gè)MinioClient對(duì)象
MinioClient minioClient = new MinioClient("http://172.16.10.201:9000/", "minioadmin", "minioadmin");
// 檢查存儲(chǔ)桶是否已經(jīng)存在
boolean isExist = minioClient.bucketExists("spacedata");
if (isExist) {
System.out.println("Bucket already exists.");
} else {
// 創(chuàng)建一個(gè)名為asiatrip的存儲(chǔ)桶,用于存儲(chǔ)照片的zip文件。
minioClient.makeBucket("spacedata");
}
// 使用putObject上傳一個(gè)文件到存儲(chǔ)桶中。
// minioClient.putObject("spacedata", "測(cè)試.jpg", "C:\\Users\\sundasheng44\\Desktop\\1.png");
// minioClient.removeObject("spacedata", "20200916/8ca27855ba884d7da1496fb96907a759.dwg");
Iterable<Result<Item>> list = minioClient.listObjects("spacedata", "CompileResult/");
List<String> list1 = Lists.newArrayList();
list.forEach(e -> {
try {
list1.add("1");
String url = minioClient.getObjectUrl("spacedata", e.get().objectName());
System.out.println(url);
//getFile(url, "C:\\Users\\liuya\\Desktop\\" + e.get().objectName());
System.out.println(e.get().objectName());
// minioClient.removeObject("spacedata", e.get().objectName());
} catch (InvalidBucketNameException invalidBucketNameException) {
invalidBucketNameException.printStackTrace();
} catch (NoSuchAlgorithmException noSuchAlgorithmException) {
noSuchAlgorithmException.printStackTrace();
} catch (InsufficientDataException insufficientDataException) {
insufficientDataException.printStackTrace();
} catch (IOException ioException) {
ioException.printStackTrace();
} catch (InvalidKeyException invalidKeyException) {
invalidKeyException.printStackTrace();
} catch (NoResponseException noResponseException) {
noResponseException.printStackTrace();
} catch (XmlPullParserException xmlPullParserException) {
xmlPullParserException.printStackTrace();
} catch (ErrorResponseException errorResponseException) {
errorResponseException.printStackTrace();
} catch (InternalException internalException) {
internalException.printStackTrace();
}
});
System.out.println(list1.size());
} catch (MinioException e) {
System.out.println("Error occurred: " + e);
}
}
/**
* 文件流下載(原始文件名)
*
* @author sunboqiang
* @date 2020/10/22
*/
public ResponseEntity<byte[]> fileDownload(String url, String fileName, HttpServletRequest request) {
return this.downloadMethod(url, fileName, request);
}
private File getFile(String url, String fileName) {
InputStream in = null;
// 創(chuàng)建文件
String dirPath = fileName.substring(0, fileName.lastIndexOf("/"));
File dir = new File(dirPath);
if (!dir.exists()) {
dir.mkdirs();
}
File file = new File(fileName);
try {
URL url1 = new URL(url);
in = url1.openStream();
// 輸入流轉(zhuǎn)換為字節(jié)流
byte[] buffer = FileCopyUtils.copyToByteArray(in);
// 字節(jié)流寫入文件
FileCopyUtils.copy(buffer, file);
// 關(guān)閉輸入流
in.close();
} catch (IOException e) {
log.error("文件獲取失?。? + e);
return null;
} finally {
try {
in.close();
} catch (IOException e) {
log.error("", e);
}
}
return file;
}
public ResponseEntity<byte[]> downloadMethod(String url, String fileName, HttpServletRequest request) {
HttpHeaders heads = new HttpHeaders();
heads.add(HttpHeaders.CONTENT_TYPE, "application/octet-stream; charset=utf-8");
try {
if (request.getHeader("User-Agent").toLowerCase().indexOf("firefox") > 0) {
// firefox瀏覽器
fileName = new String(fileName.getBytes(StandardCharsets.UTF_8), "ISO8859-1");
} else if (request.getHeader("User-Agent").toUpperCase().indexOf("MSIE") > 0) {
// IE瀏覽器
fileName = URLEncoder.encode(fileName, "UTF-8");
} else if (request.getHeader("User-Agent").toUpperCase().indexOf("EDGE") > 0) {
// WIN10瀏覽器
fileName = URLEncoder.encode(fileName, "UTF-8");
} else if (request.getHeader("User-Agent").toUpperCase().indexOf("CHROME") > 0) {
// 谷歌
fileName = new String(fileName.getBytes(StandardCharsets.UTF_8), "ISO8859-1");
} else {
//萬能亂碼問題解決
fileName = new String(fileName.getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1);
}
} catch (UnsupportedEncodingException e) {
// log.error("", e);
}
heads.add(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=" + fileName);
try {
//InputStream in = new FileInputStream(file);
URL url1 = new URL(url);
InputStream in = url1.openStream();
// 輸入流轉(zhuǎn)換為字節(jié)流
byte[] buffer = FileCopyUtils.copyToByteArray(in);
ResponseEntity<byte[]> responseEntity = new ResponseEntity<>(buffer, heads, HttpStatus.OK);
//file.delete();
return responseEntity;
} catch (Exception e) {
log.error("", e);
}
return null;
}創(chuàng)建 FilesMinioService 服務(wù)類
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.gis.spacedata.common.constant.response.ResponseCodeConst;
import com.gis.spacedata.common.domain.ResponseDTO;
import com.gis.spacedata.domain.dto.file.vo.UploadVO;
import com.gis.spacedata.domain.dto.minio.MinioItem;
import com.gis.spacedata.domain.entity.file.FileEntity;
import com.gis.spacedata.enums.file.FileServiceTypeEnum;
import com.gis.spacedata.handler.SmartBusinessException;
import com.gis.spacedata.mapper.file.FileDao;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils;
import org.springblade.core.tool.utils.FileUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.ResponseEntity;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.UUID;
@Service
@Slf4j
public class FilesMinioService extends ServiceImpl<FileDao, FileEntity> {
@Autowired
private MinioTemplate minioTemplate;
@Resource
private ThreadPoolTaskExecutor taskExecutor;
/**
* 圖片大小限制
**/
@Value("#{${minio.imgSize}}")
private Long imgSize;
/**
* 文件大小限制
**/
@Value("#{${minio.fileSize}}")
private Long fileSize;
@Value("${minio.bucket}")
private String bucket;
/**
* 下載地址
**/
@Value("${minio.http-url}")
private String httpUrl;
/**
* 判斷是否圖片
*/
private boolean isImage(String fileName) {
//設(shè)置允許上傳文件類型
String suffixList = "jpg,gif,png,ico,bmp,jpeg";
// 獲取文件后綴
String suffix = fileName.substring(fileName.lastIndexOf(".")
+ 1);
return suffixList.contains(suffix.trim().toLowerCase());
}
/**
* 驗(yàn)證文件大小
*
* @param upfile
* @param fileName 文件名稱
* @throws Exception
*/
private void fileCheck(MultipartFile upfile, String fileName) throws Exception {
Long size = upfile.getSize();
if (isImage(fileName)) {
if (size > imgSize) {
throw new Exception("上傳對(duì)圖片大于:" + (imgSize / 1024 / 1024) + "M限制");
}
} else {
if (size > fileSize) {
throw new Exception("上傳對(duì)文件大于:" + (fileSize / 1024 / 1024) + "M限制");
}
}
}
/**
* 文件上傳
*
* @author sunboqiang
* @date 2020/9/9
*/
public ResponseDTO<UploadVO> fileUpload(MultipartFile upfile) throws IOException {
String originalFileName = upfile.getOriginalFilename();
try {
fileCheck(upfile, originalFileName);
} catch (Exception e) {
return ResponseDTO.wrap(ResponseCodeConst.ERROR, e.getMessage());
}
if (StringUtils.isBlank(originalFileName)) {
return ResponseDTO.wrap(ResponseCodeConst.ERROR_PARAM, "文件名稱不能為空");
}
UploadVO vo = new UploadVO();
String url;
//獲取文件md5,查找數(shù)據(jù)庫(kù),如果有,則不需要上傳了
String md5 = DigestUtils.md5Hex(upfile.getInputStream());
QueryWrapper<FileEntity> query = new QueryWrapper<>();
query.lambda().eq(FileEntity::getMd5, md5);
query.lambda().eq(FileEntity::getStorageType, FileServiceTypeEnum.MINIO_OSS.getLocationType());
FileEntity fileEntity = baseMapper.selectOne(query);
if (null != fileEntity) {
//url = minioTemplate.getObjectURL(bucket,fileEntity.getFileName());
vo.setId(fileEntity.getId());
vo.setFileName(originalFileName);
vo.setUrl(httpUrl + fileEntity.getFileUrl());
vo.setNewFileName(fileEntity.getFileName());
vo.setFileSize(upfile.getSize());
vo.setFileLocationType(FileServiceTypeEnum.MINIO_OSS.getLocationType());
log.info("文件已上傳,直接獲取");
return ResponseDTO.succData(vo);
}
//拼接文件名
String fileName = generateFileName(originalFileName);
try {
// 檢查存儲(chǔ)桶是否已經(jīng)存在
boolean isExist = minioTemplate.bucketExists(bucket);
if (isExist) {
log.info("Bucket already exists.");
} else {
// 創(chuàng)建一個(gè)名為asiatrip的存儲(chǔ)桶,用于存儲(chǔ)照片的zip文件。
minioTemplate.createBucket(bucket);
}
// 使用putObject上傳一個(gè)文件到存儲(chǔ)桶中。
minioTemplate.putObject(bucket, fileName, upfile.getInputStream());
log.info("上傳成功.");
//生成一個(gè)外部鏈接
//url = minioTemplate.getObjectURL(bucket,fileName);
//已經(jīng)設(shè)置永久鏈接,直接獲取
url = httpUrl + bucket + "/" + fileName;
fileEntity = new FileEntity();
fileEntity.setStorageType(FileServiceTypeEnum.MINIO_OSS.getLocationType());
fileEntity.setFileName(fileName);
fileEntity.setOriginalFileName(originalFileName);
fileEntity.setFileUrl(bucket + "/" + fileName);
fileEntity.setFileSize(upfile.getSize());
fileEntity.setMd5(md5);
baseMapper.insert(fileEntity);
} catch (Exception e) {
return ResponseDTO.wrap(ResponseCodeConst.ERROR, "上傳失??!");
}
vo.setFileName(originalFileName);
vo.setId(fileEntity.getId());
vo.setUrl(url);
vo.setNewFileName(fileName);
vo.setFileSize(upfile.getSize());
vo.setFileLocationType(FileServiceTypeEnum.MINIO_OSS.getLocationType());
return ResponseDTO.succData(vo);
}
/**
* 生成文件名字
* 當(dāng)前年月日時(shí)分秒 +32位 uuid + 文件格式后綴
*
* @param originalFileName
* @return String
*/
private String generateFileName(String originalFileName) {
String time = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"));
String uuid = UUID.randomUUID().toString().replaceAll("-", "");
String fileType = originalFileName.substring(originalFileName.lastIndexOf("."));
return time + "/" + uuid + fileType;
}
/**
* 文件上傳(不做重復(fù)校驗(yàn))
*
* @author sunboqiang
* @date 2020/9/25
*/
public ResponseDTO<UploadVO> fileUploadRep(MultipartFile upfile) throws IOException {
String originalFileName = upfile.getOriginalFilename();
try {
fileCheck(upfile, originalFileName);
} catch (Exception e) {
return ResponseDTO.wrap(ResponseCodeConst.ERROR, e.getMessage());
}
if (StringUtils.isBlank(originalFileName)) {
return ResponseDTO.wrap(ResponseCodeConst.ERROR_PARAM, "文件名稱不能為空");
}
UploadVO vo = new UploadVO();
String url;
//獲取文件md5
FileEntity fileEntity = new FileEntity();
//拼接文件名
String fileName = generateFileName(originalFileName);
try {
// 檢查存儲(chǔ)桶是否已經(jīng)存在
boolean isExist = minioTemplate.bucketExists(bucket);
if (isExist) {
log.info("Bucket already exists.");
} else {
// 創(chuàng)建一個(gè)名為asiatrip的存儲(chǔ)桶,用于存儲(chǔ)照片的zip文件。
minioTemplate.createBucket(bucket);
}
// 使用putObject上傳一個(gè)文件到存儲(chǔ)桶中。
minioTemplate.putObject(bucket, fileName, upfile.getInputStream());
log.info("上傳成功.");
//生成一個(gè)外部鏈接
//url = minioTemplate.getObjectURL(bucket,fileName);
//已經(jīng)設(shè)置永久鏈接,直接獲取
url = httpUrl + bucket + "/" + fileName;
fileEntity.setStorageType(FileServiceTypeEnum.MINIO_OSS.getLocationType());
fileEntity.setFileName(fileName);
fileEntity.setOriginalFileName(originalFileName);
fileEntity.setFileUrl(bucket + "/" + fileName);
fileEntity.setFileSize(upfile.getSize());
baseMapper.insert(fileEntity);
} catch (Exception e) {
return ResponseDTO.wrap(ResponseCodeConst.ERROR, "上傳失??!");
}
vo.setFileName(originalFileName);
vo.setId(fileEntity.getId());
vo.setUrl(url);
vo.setNewFileName(fileName);
vo.setFileSize(upfile.getSize());
vo.setFileLocationType(FileServiceTypeEnum.MINIO_OSS.getLocationType());
return ResponseDTO.succData(vo);
}
/**
* 文件流上傳(不存數(shù)據(jù)庫(kù))
*
* @author sunboqiang
* @date 2020/9/25
*/
public ResponseDTO<UploadVO> uploadStream(InputStream inputStream, String originalFileName) {
UploadVO vo = new UploadVO();
String url;
//文件名
String fileName = originalFileName;
try {
// 檢查存儲(chǔ)桶是否已經(jīng)存在
boolean isExist = minioTemplate.bucketExists(bucket);
if (isExist) {
log.info("Bucket already exists.");
} else {
// 創(chuàng)建一個(gè)名為asiatrip的存儲(chǔ)桶,用于存儲(chǔ)照片的zip文件。
minioTemplate.createBucket(bucket);
}
// 使用putObject上傳一個(gè)文件到存儲(chǔ)桶中。
minioTemplate.putObject(bucket, fileName, inputStream);
log.info("上傳成功.");
//生成一個(gè)外部鏈接
//url = minioTemplate.getObjectURL(bucket,fileName);
//已經(jīng)設(shè)置永久鏈接,直接獲取
url = httpUrl + bucket + "/" + fileName;
} catch (Exception e) {
return ResponseDTO.wrap(ResponseCodeConst.ERROR, "上傳失敗!");
}
vo.setFileName(originalFileName);
vo.setUrl(url);
vo.setNewFileName(fileName);
vo.setFileLocationType(FileServiceTypeEnum.MINIO_OSS.getLocationType());
return ResponseDTO.succData(vo);
}
private String generateFileNameTwo(String originalFileName) {
String time = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"));
return time + "/" + originalFileName;
}
/**
* 文件查詢
*
* @author sunboqiang
* @date 2020/9/25
*/
public ResponseDTO<UploadVO> findFileById(Long id) {
FileEntity fileEntity = baseMapper.selectById(id);
if (null == fileEntity) {
return ResponseDTO.wrap(ResponseCodeConst.ERROR_PARAM, "文件不存在");
}
UploadVO vo = new UploadVO();
/*String url = minioTemplate.getObjectURL(bucket,fileEntity.getFileName());
if(StringUtils.isEmpty(url)){
return ResponseDTO.wrap(ResponseCodeConst.ERROR_PARAM,"獲取minio 文件url失敗!");
}*/
vo.setFileName(fileEntity.getOriginalFileName());
vo.setUrl(httpUrl + fileEntity.getFileUrl());
vo.setNewFileName(fileEntity.getFileName());
vo.setFileSize(fileEntity.getFileSize());
vo.setFileLocationType(FileServiceTypeEnum.MINIO_OSS.getLocationType());
return ResponseDTO.succData(vo);
}
/**
* 文件流式下載
*
* @author sunboqiang
* @date 2020/10/22
*/
public ResponseEntity<byte[]> downLoadFile(Long id, HttpServletRequest request) {
FileEntity fileEntity = baseMapper.selectById(id);
if (null == fileEntity) {
throw new SmartBusinessException("文件信息不存在");
}
if (StringUtils.isEmpty(fileEntity.getFileUrl())) {
throw new SmartBusinessException("文件url為空");
}
ResponseEntity<byte[]> stream = minioTemplate.fileDownload(httpUrl + fileEntity.getFileUrl(), fileEntity.getOriginalFileName(), request);
return stream;
}
/**
* 文件刪除(通過文件名)
*
* @author tarzan Liu
* @date 2020/11/11
*/
public ResponseDTO<String> deleteFiles(List<String> fileNames) {
try {
for (String fileName : fileNames) {
minioTemplate.removeObject(bucket, fileName);
}
} catch (Exception e) {
return ResponseDTO.wrap(ResponseCodeConst.ERROR, e.getMessage());
}
return ResponseDTO.succ();
}
/**
* tarzan LIU
*
* @author tarzan Liu
* @date 2020/11/11
*/
public ResponseDTO<String> downloadTargetDir(String objectName, String dirPath) {
minioTemplate.downloadTargetDir(bucket, objectName, dirPath);
return ResponseDTO.succ();
}
/**
* 下載備份編譯結(jié)果
*
* @param dirPath
* @return {@link Boolean}
* @author zhangpeng
* @date 2021年10月15日
*/
public Boolean downloadCompile(String dirPath) {
if (!minioTemplate.bucketExists(bucket)) {
log.info("Bucket not exists.");
return true;
}
List<MinioItem> list = minioTemplate.getAllObjectsByPrefix(bucket, "CompileResult/", true);
list.forEach(e -> {
String url = minioTemplate.getObjectUrl(bucket, e.getObjectName());
InputStream minioStream = minioTemplate.getObject(bucket, e.getObjectName());
File file = new File(dirPath + url.substring(url.indexOf("CompileResult")-1));
if (!file.getParentFile().exists()) {
file.getParentFile().mkdirs();
}
FileUtil.toFile(minioStream, file);
});
log.info("downloadCompile complete.");
return true;
}部分操作數(shù)據(jù)庫(kù)的相關(guān)代碼省略,不再展示
創(chuàng)建FilesMinioController 服務(wù)接口
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.gis.spacedata.common.anno.NoNeedLogin;
import com.gis.spacedata.common.domain.ResponseDTO;
import com.gis.spacedata.domain.dto.file.vo.UploadVO;
import com.gis.spacedata.service.file.FilesMinioService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletRequest;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import java.util.List;
@Api(tags = {"minio文件服務(wù)"})
@RestController
public class FilesMinioController {
@Autowired
private FilesMinioService filesMinioService;
@ApiOperation(value = "文件上傳(md5去重上傳) by sunboqiang")
@PostMapping("/minio/uploadFile/md5")
@NoNeedLogin
public ResponseDTO<UploadVO> uploadFile(MultipartFile file) throws IOException {
return filesMinioService.fileUpload(file);
}
@ApiOperation(value = "文件上傳(不做重復(fù)校驗(yàn)) by sunboqiang")
@PostMapping("/minio/uploadFile/noRepeatCheck")
public ResponseDTO<UploadVO> fileUploadRep(MultipartFile file) throws IOException {
return filesMinioService.fileUploadRep(file);
}
@ApiOperation(value = "文件流上傳 by sunboqiang")
@PostMapping("/minio/uploadFile/stream/{fileName}")
public ResponseDTO<UploadVO> uploadStream(InputStream inputStream, @PathVariable("fileName") String fileName) throws IOException {
return filesMinioService.uploadStream(inputStream, fileName);
}
@ApiOperation(value = "文件查詢(永久鏈接) by sunboqiang")
@GetMapping("/minio/getFileUrl/{id}")
public ResponseDTO<UploadVO> findFileById(@PathVariable("id") Long id) {
return filesMinioService.findFileById(id);
}
@ApiOperation(value = "文件流式下載 by sunboqiang")
@GetMapping("/minio/downloadFile/stream")
public ResponseEntity<byte[]> downLoadFile(@RequestParam Long id, HttpServletRequest request) {
return filesMinioService.downLoadFile(id, request);
}
@ApiOperation(value = "文件刪除(通過文件名) by sunboqiang")
@PostMapping("/minio/deleteFiles")
public ResponseDTO<String> deleteFiles(@RequestBody List<String> fileNames) {
return filesMinioService.deleteFiles(fileNames);
}
}以上就是Springboot整合minio實(shí)現(xiàn)文件服務(wù)的教程詳解的詳細(xì)內(nèi)容,更多關(guān)于Springboot minio文件服務(wù)的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
- SpringBoot+MinIO實(shí)現(xiàn)對(duì)象存儲(chǔ)的示例詳解
- SpringBoot基于Minio實(shí)現(xiàn)分片上傳、斷點(diǎn)續(xù)傳的實(shí)現(xiàn)
- springboot?Minio功能實(shí)現(xiàn)代碼
- SpringBoot集成MinIO的示例代碼
- SpringBoot + minio實(shí)現(xiàn)分片上傳、秒傳、續(xù)傳功能
- SpringBoot整合minio服務(wù)的示例代碼
- SpringBoot整合Minio的示例代碼
- SpringBoot使用Minio進(jìn)行文件存儲(chǔ)的實(shí)現(xiàn)
- 可能是全網(wǎng)最詳細(xì)的springboot整合minio教程
- SpringBoot整合Minio實(shí)現(xiàn)上傳文件的完整步驟記錄
- SpringBoot整合MinIO實(shí)現(xiàn)文件上傳的方法詳解
- SpringBoot整合minio快速入門教程(代碼示例)
- SpringBoot+MinIO實(shí)現(xiàn)文件上傳、讀取、下載、刪除的使用示例
相關(guān)文章
IDEA配置靜態(tài)資源熱加載操作(Springboot修改靜態(tài)資源不重啟)
這篇文章主要介紹了IDEA配置靜態(tài)資源熱加載操作(Springboot修改靜態(tài)資源不重啟),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2020-10-10
Java使用正則表達(dá)式刪除所有HTML標(biāo)簽的方法示例
這篇文章主要介紹了Java使用正則表達(dá)式刪除所有HTML標(biāo)簽的方法,結(jié)合完整實(shí)例形式分析了java針對(duì)HTML頁(yè)面元素script標(biāo)簽、style標(biāo)簽、html標(biāo)簽等的正則匹配相關(guān)操作技巧,需要的朋友可以參考下2017-06-06
Spring?Security權(quán)限管理小結(jié)
SpringSecurity是一個(gè)權(quán)限管理框架,核心是認(rèn)證和授權(quán),前面已經(jīng)系統(tǒng)的給大家介紹過了認(rèn)證的實(shí)現(xiàn)和源碼分析,本文重點(diǎn)來介紹下權(quán)限管理,需要的朋友可以參考下2022-08-08
Java Web實(shí)現(xiàn)添加定時(shí)任務(wù)的方法示例
這篇文章主要介紹了Java Web實(shí)現(xiàn)添加定時(shí)任務(wù)的方法,涉及java web定時(shí)任務(wù)控制類定義、調(diào)用及監(jiān)聽器定義、添加等相關(guān)操作技巧,需要的朋友可以參考下2018-01-01
spring/springboot整合curator遇到的坑及解決
這篇文章主要介紹了spring/springboot整合curator遇到的坑及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-05-05
SpringMvc框架的簡(jiǎn)介與執(zhí)行流程詳解
MVC是一種軟件設(shè)計(jì)典范,用一種業(yè)務(wù)邏輯、數(shù)據(jù)、界面顯示分離的方法組織代碼,將業(yè)務(wù)邏輯聚集到一個(gè)組件里面,在改進(jìn)和個(gè)性化定制界面及用戶交互的同時(shí),不需要重新編寫業(yè)務(wù)邏輯,MVC分層有助于管理和架構(gòu)復(fù)雜的應(yīng)用程序2021-06-06
Struts2實(shí)現(xiàn)文件上傳時(shí)顯示進(jìn)度條功能
這篇文章主要為大家詳細(xì)介紹了Struts2實(shí)現(xiàn)文件上傳時(shí)顯示進(jìn)度條功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-05-05

