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 過(guò)期時(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é)流寫(xiě)入文件 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 { //萬(wàn)能亂碼問(wèn)題解決 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; } /** * 文件刪除(通過(guò)文件名) * * @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 = "文件刪除(通過(guò)文件名) 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快速入門(mén)教程(代碼示例)
- SpringBoot+MinIO實(shí)現(xiàn)文件上傳、讀取、下載、刪除的使用示例
相關(guān)文章
IDEA配置靜態(tài)資源熱加載操作(Springboot修改靜態(tài)資源不重啟)
這篇文章主要介紹了IDEA配置靜態(tài)資源熱加載操作(Springboot修改靜態(tài)資源不重啟),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-10-10Java使用正則表達(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-06Spring?Security權(quán)限管理小結(jié)
SpringSecurity是一個(gè)權(quán)限管理框架,核心是認(rèn)證和授權(quán),前面已經(jīng)系統(tǒng)的給大家介紹過(guò)了認(rèn)證的實(shí)現(xiàn)和源碼分析,本文重點(diǎn)來(lái)介紹下權(quán)限管理,需要的朋友可以參考下2022-08-08Java Web實(shí)現(xiàn)添加定時(shí)任務(wù)的方法示例
這篇文章主要介紹了Java Web實(shí)現(xiàn)添加定時(shí)任務(wù)的方法,涉及java web定時(shí)任務(wù)控制類定義、調(diào)用及監(jiān)聽(tīng)器定義、添加等相關(guān)操作技巧,需要的朋友可以參考下2018-01-01spring/springboot整合curator遇到的坑及解決
這篇文章主要介紹了spring/springboot整合curator遇到的坑及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-05-05SpringMvc框架的簡(jiǎn)介與執(zhí)行流程詳解
MVC是一種軟件設(shè)計(jì)典范,用一種業(yè)務(wù)邏輯、數(shù)據(jù)、界面顯示分離的方法組織代碼,將業(yè)務(wù)邏輯聚集到一個(gè)組件里面,在改進(jìn)和個(gè)性化定制界面及用戶交互的同時(shí),不需要重新編寫(xiě)業(yè)務(wù)邏輯,MVC分層有助于管理和架構(gòu)復(fù)雜的應(yīng)用程序2021-06-06Struts2實(shí)現(xiàn)文件上傳時(shí)顯示進(jìn)度條功能
這篇文章主要為大家詳細(xì)介紹了Struts2實(shí)現(xiàn)文件上傳時(shí)顯示進(jìn)度條功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-05-05