20 changed files with 507 additions and 29 deletions
@ -0,0 +1,39 @@ |
|||
package com.lx.common.enums; |
|||
|
|||
public enum FileTypeEnum { |
|||
|
|||
FILE(0,"文件"), |
|||
IMAGE(1,"图片"), |
|||
VIDEO(2,"视频"); |
|||
|
|||
|
|||
private Integer code; |
|||
|
|||
private String desc; |
|||
|
|||
FileTypeEnum(Integer index, String desc) { |
|||
this.code =index; |
|||
this.desc=desc; |
|||
} |
|||
|
|||
public static FileTypeEnum fromCode(Integer code){ |
|||
for (FileTypeEnum typeEnum:values()) { |
|||
if (typeEnum.code.equals(code)) { |
|||
return typeEnum; |
|||
} |
|||
} |
|||
return null; |
|||
} |
|||
|
|||
|
|||
public String getDesc() { |
|||
return desc; |
|||
} |
|||
|
|||
public Integer getCode(){ |
|||
return this.code; |
|||
} |
|||
|
|||
|
|||
} |
|||
|
|||
@ -0,0 +1,31 @@ |
|||
package com.lx.implatform.config; |
|||
|
|||
import io.minio.MinioClient; |
|||
import org.springframework.beans.factory.annotation.Value; |
|||
import org.springframework.context.annotation.Bean; |
|||
import org.springframework.context.annotation.Configuration; |
|||
|
|||
|
|||
@Configuration |
|||
public class MinIoClientConfig { |
|||
@Value("${minio.endpoint}") |
|||
private String endpoint; |
|||
@Value("${minio.accessKey}") |
|||
private String accessKey; |
|||
@Value("${minio.secretKey}") |
|||
private String secretKey; |
|||
|
|||
/** |
|||
* 注入minio 客户端 |
|||
* @return |
|||
*/ |
|||
@Bean |
|||
public MinioClient minioClient(){ |
|||
|
|||
MinioClient client = MinioClient.builder() |
|||
.endpoint(endpoint) |
|||
.credentials(accessKey, secretKey) |
|||
.build(); |
|||
return client; |
|||
} |
|||
} |
|||
@ -0,0 +1,42 @@ |
|||
package com.lx.implatform.controller; |
|||
|
|||
import com.lx.common.result.Result; |
|||
import com.lx.common.result.ResultUtils; |
|||
import com.lx.implatform.service.thirdparty.FileService; |
|||
import io.swagger.annotations.Api; |
|||
import io.swagger.annotations.ApiOperation; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.springframework.beans.factory.annotation.Autowired; |
|||
import org.springframework.web.bind.annotation.GetMapping; |
|||
import org.springframework.web.bind.annotation.PostMapping; |
|||
import org.springframework.web.bind.annotation.RestController; |
|||
import org.springframework.web.multipart.MultipartFile; |
|||
|
|||
/* |
|||
* 文件上传 |
|||
* @Author Blue |
|||
* @Date 2022/10/28 |
|||
*/ |
|||
@Slf4j |
|||
@RestController |
|||
@Api(tags = "文件上传") |
|||
public class FileController { |
|||
|
|||
|
|||
@Autowired |
|||
private FileService fileService; |
|||
|
|||
@ApiOperation(value = "上传图片",notes="上传图片") |
|||
@PostMapping("/image/upload") |
|||
public Result upload(MultipartFile file) { |
|||
return ResultUtils.success(fileService.uploadImage(file)); |
|||
} |
|||
|
|||
|
|||
@GetMapping("/online") |
|||
@ApiOperation(value = "查找用户",notes="根据昵称查找用户") |
|||
public Result checkOnline(){ |
|||
|
|||
return ResultUtils.success(""); |
|||
} |
|||
} |
|||
@ -0,0 +1,83 @@ |
|||
package com.lx.implatform.service.thirdparty; |
|||
|
|||
import com.lx.common.enums.FileTypeEnum; |
|||
import com.lx.common.enums.ResultCode; |
|||
import com.lx.implatform.exception.GlobalException; |
|||
import com.lx.implatform.util.ImageUtil; |
|||
import com.lx.implatform.util.MinioUtil; |
|||
import com.lx.implatform.vo.UploadImageVO; |
|||
import lombok.extern.slf4j.Slf4j; |
|||
import org.springframework.beans.factory.annotation.Autowired; |
|||
import org.springframework.beans.factory.annotation.Value; |
|||
import org.springframework.stereotype.Service; |
|||
import org.springframework.web.multipart.MultipartFile; |
|||
|
|||
import javax.annotation.PostConstruct; |
|||
import java.io.IOException; |
|||
|
|||
/* |
|||
* 文件上传服务 |
|||
* @Author Blue |
|||
* @Date 2022/10/28 |
|||
*/ |
|||
@Slf4j |
|||
@Service |
|||
public class FileService { |
|||
|
|||
@Autowired |
|||
private MinioUtil minioUtil; |
|||
|
|||
@Value("${minio.public}") |
|||
private String minIOServer; |
|||
@Value("${minio.bucketName}") |
|||
private String bucketName; |
|||
|
|||
@Value("${minio.imagePath}") |
|||
private String imagePath; |
|||
|
|||
@Value("${minio.filePath}") |
|||
private String filePath; |
|||
|
|||
@PostConstruct |
|||
public void init(){ |
|||
if(!minioUtil.bucketExists(bucketName)){ |
|||
minioUtil.makeBucket(bucketName); |
|||
} |
|||
} |
|||
|
|||
public UploadImageVO uploadImage(MultipartFile file){ |
|||
try { |
|||
UploadImageVO vo = new UploadImageVO(); |
|||
|
|||
String fileName = minioUtil.upload(bucketName,imagePath,file); |
|||
vo.setOriginUrl(generUrl(FileTypeEnum.IMAGE,fileName)); |
|||
// 上传缩略图
|
|||
byte[] imageByte = ImageUtil.compressForScale(file.getBytes(),100); |
|||
fileName = minioUtil.upload(bucketName,imagePath,file.getOriginalFilename(),imageByte,file.getContentType()); |
|||
vo.setCompressUrl(generUrl(FileTypeEnum.IMAGE,fileName)); |
|||
return vo; |
|||
} catch (IOException e) { |
|||
log.error("上传图片失败,{}",e.getMessage(),e); |
|||
throw new GlobalException(ResultCode.PROGRAM_ERROR,"图片上传失败"); |
|||
} |
|||
} |
|||
|
|||
|
|||
public String generUrl(FileTypeEnum fileTypeEnum, String fileName){ |
|||
String url = minIOServer+"/"+bucketName; |
|||
switch (fileTypeEnum){ |
|||
case FILE: |
|||
url += "/file/"; |
|||
break; |
|||
case IMAGE: |
|||
url += "/image/"; |
|||
break; |
|||
case VIDEO: |
|||
url += "/video/"; |
|||
break; |
|||
} |
|||
url += fileName; |
|||
return url; |
|||
} |
|||
|
|||
} |
|||
@ -0,0 +1,78 @@ |
|||
package com.lx.implatform.util; |
|||
|
|||
|
|||
import lombok.extern.slf4j.Slf4j; |
|||
import net.coobird.thumbnailator.Thumbnails; |
|||
|
|||
import java.io.ByteArrayInputStream; |
|||
import java.io.ByteArrayOutputStream; |
|||
|
|||
@Slf4j |
|||
public class ImageUtil { |
|||
|
|||
//以下是常量,按照阿里代码开发规范,不允许代码中出现魔法值
|
|||
private static final Integer ZERO = 0; |
|||
private static final Integer ONE_ZERO_TWO_FOUR = 1024; |
|||
private static final Integer NINE_ZERO_ZERO = 900; |
|||
private static final Integer THREE_TWO_SEVEN_FIVE = 3275; |
|||
private static final Integer TWO_ZERO_FOUR_SEVEN = 2047; |
|||
private static final Double ZERO_EIGHT_FIVE = 0.85; |
|||
private static final Double ZERO_SIX = 0.6; |
|||
private static final Double ZERO_FOUR_FOUR = 0.44; |
|||
private static final Double ZERO_FOUR = 0.4; |
|||
|
|||
/** |
|||
* 根据指定大小压缩图片 |
|||
* |
|||
* @param imageBytes 源图片字节数组 |
|||
* @param desFileSize 指定图片大小,单位kb |
|||
* @return 压缩质量后的图片字节数组 |
|||
*/ |
|||
public static byte[] compressForScale(byte[] imageBytes, long desFileSize) { |
|||
if (imageBytes == null || imageBytes.length <= ZERO || imageBytes.length < desFileSize * ONE_ZERO_TWO_FOUR) { |
|||
return imageBytes; |
|||
} |
|||
long srcSize = imageBytes.length; |
|||
double accuracy = getAccuracy(srcSize / ONE_ZERO_TWO_FOUR); |
|||
try { |
|||
while (imageBytes.length > desFileSize * ONE_ZERO_TWO_FOUR) { |
|||
ByteArrayInputStream inputStream = new ByteArrayInputStream(imageBytes); |
|||
ByteArrayOutputStream outputStream = new ByteArrayOutputStream(imageBytes.length); |
|||
Thumbnails.of(inputStream) |
|||
.scale(accuracy) |
|||
.outputQuality(accuracy) |
|||
.toOutputStream(outputStream); |
|||
imageBytes = outputStream.toByteArray(); |
|||
} |
|||
log.info("图片原大小={}kb | 压缩后大小={}kb", |
|||
srcSize / ONE_ZERO_TWO_FOUR, imageBytes.length / ONE_ZERO_TWO_FOUR); |
|||
} catch (Exception e) { |
|||
log.error("【图片压缩】msg=图片压缩失败!", e); |
|||
} |
|||
return imageBytes; |
|||
} |
|||
|
|||
/** |
|||
* 自动调节精度(经验数值) |
|||
* |
|||
* @param size 源图片大小 |
|||
* @return 图片压缩质量比 |
|||
*/ |
|||
private static double getAccuracy(long size) { |
|||
double accuracy; |
|||
if (size < NINE_ZERO_ZERO) { |
|||
accuracy = ZERO_EIGHT_FIVE; |
|||
} else if (size < TWO_ZERO_FOUR_SEVEN) { |
|||
accuracy = ZERO_SIX; |
|||
} else if (size < THREE_TWO_SEVEN_FIVE) { |
|||
accuracy = ZERO_FOUR_FOUR; |
|||
} else { |
|||
accuracy = ZERO_FOUR; |
|||
} |
|||
return accuracy; |
|||
} |
|||
|
|||
} |
|||
|
|||
|
|||
|
|||
@ -0,0 +1,139 @@ |
|||
package com.lx.implatform.util; |
|||
|
|||
|
|||
import com.lx.common.util.DateTimeUtils; |
|||
import io.minio.*; |
|||
import org.apache.commons.lang3.StringUtils; |
|||
import org.springframework.beans.factory.annotation.Autowired; |
|||
import org.springframework.stereotype.Component; |
|||
import org.springframework.web.multipart.MultipartFile; |
|||
|
|||
import java.io.ByteArrayInputStream; |
|||
import java.io.InputStream; |
|||
import java.util.Date; |
|||
|
|||
@Component |
|||
public class MinioUtil { |
|||
|
|||
|
|||
@Autowired |
|||
private MinioClient minioClient; |
|||
|
|||
/** |
|||
* 查看存储bucket是否存在 |
|||
* @return boolean |
|||
*/ |
|||
public Boolean bucketExists(String bucketName) { |
|||
Boolean found; |
|||
try { |
|||
found = minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build()); |
|||
} catch (Exception e) { |
|||
e.printStackTrace(); |
|||
return false; |
|||
} |
|||
return found; |
|||
} |
|||
|
|||
/** |
|||
* 创建存储bucket |
|||
* @return Boolean |
|||
*/ |
|||
public Boolean makeBucket(String bucketName) { |
|||
try { |
|||
minioClient.makeBucket(MakeBucketArgs.builder() |
|||
.bucket(bucketName) |
|||
.build()); |
|||
} catch (Exception e) { |
|||
e.printStackTrace(); |
|||
return false; |
|||
} |
|||
return true; |
|||
} |
|||
|
|||
/** |
|||
* 删除存储bucket |
|||
* @return Boolean |
|||
*/ |
|||
public Boolean removeBucket(String bucketName) { |
|||
try { |
|||
minioClient.removeBucket(RemoveBucketArgs.builder() |
|||
.bucket(bucketName) |
|||
.build()); |
|||
} catch (Exception e) { |
|||
e.printStackTrace(); |
|||
return false; |
|||
} |
|||
return true; |
|||
} |
|||
|
|||
|
|||
/** |
|||
* 文件上传 |
|||
* @bucketName bucket名称 |
|||
* @path 路径 |
|||
* @param file 文件 |
|||
* @return Boolean |
|||
*/ |
|||
public String upload(String bucketName,String path,MultipartFile file) { |
|||
String originalFilename = file.getOriginalFilename(); |
|||
if (StringUtils.isBlank(originalFilename)){ |
|||
throw new RuntimeException(); |
|||
} |
|||
String fileName = System.currentTimeMillis() + originalFilename.substring(originalFilename.lastIndexOf(".")); |
|||
String objectName = DateTimeUtils.getFormatDate(new Date(),DateTimeUtils.PARTDATEFORMAT)+ "/" + fileName; |
|||
try { |
|||
PutObjectArgs objectArgs = PutObjectArgs.builder().bucket(bucketName).object(path+"/" +objectName) |
|||
.stream(file.getInputStream(), file.getSize(), -1).contentType(file.getContentType()).build(); |
|||
//文件名称相同会覆盖
|
|||
minioClient.putObject(objectArgs); |
|||
} catch (Exception e) { |
|||
e.printStackTrace(); |
|||
return null; |
|||
} |
|||
return objectName; |
|||
} |
|||
|
|||
/** |
|||
* 文件上传 |
|||
* @param bucketName bucket名称 |
|||
* @param path 路径 |
|||
* @param name 文件名 |
|||
* @param fileByte 文件内容 |
|||
* @param contentType |
|||
* @return Boolean |
|||
*/ |
|||
public String upload(String bucketName,String path,String name,byte[] fileByte,String contentType) { |
|||
|
|||
String fileName = System.currentTimeMillis() + name.substring(name.lastIndexOf(".")); |
|||
String objectName = DateTimeUtils.getFormatDate(new Date(),DateTimeUtils.PARTDATEFORMAT)+ "/" + fileName; |
|||
try { |
|||
InputStream stream = new ByteArrayInputStream(fileByte); |
|||
PutObjectArgs objectArgs = PutObjectArgs.builder().bucket(bucketName).object(path+"/" +objectName) |
|||
.stream(stream, fileByte.length, -1).contentType(contentType).build(); |
|||
//文件名称相同会覆盖
|
|||
minioClient.putObject(objectArgs); |
|||
} catch (Exception e) { |
|||
e.printStackTrace(); |
|||
return null; |
|||
} |
|||
return objectName; |
|||
} |
|||
|
|||
|
|||
/** |
|||
* 删除 |
|||
* @param bucketName bucket名称 |
|||
* @path path |
|||
* @param fileName |
|||
* @return |
|||
* @throws Exception |
|||
*/ |
|||
public boolean remove(String bucketName,String path,String fileName){ |
|||
try { |
|||
minioClient.removeObject( RemoveObjectArgs.builder().bucket(bucketName).object(path+fileName).build()); |
|||
}catch (Exception e){ |
|||
return false; |
|||
} |
|||
return true; |
|||
} |
|||
} |
|||
@ -0,0 +1,16 @@ |
|||
package com.lx.implatform.vo; |
|||
|
|||
import io.swagger.annotations.ApiModel; |
|||
import io.swagger.annotations.ApiModelProperty; |
|||
import lombok.Data; |
|||
|
|||
@Data |
|||
@ApiModel("图片上传VO") |
|||
public class UploadImageVO { |
|||
|
|||
@ApiModelProperty(value = "原图") |
|||
private String originUrl; |
|||
|
|||
@ApiModelProperty(value = "缩略图") |
|||
private String compressUrl; |
|||
} |
|||
@ -0,0 +1,4 @@ |
|||
|
|||
set MINIO_ACCESS_KEY=admin |
|||
set MINIO_SECRET_KEY=12345678 |
|||
.\minio.exe server C:\data\minio --address ":9001" --console-address ":9002" |
|||
Loading…
Reference in new issue