+webp图片格式支持,修改OssService,提供图片缩放水印功能

master
管理员 3 years ago
parent 11f25a6010
commit ae2d31733e

@ -46,6 +46,8 @@
<!-- SMS 配置 -->
<aliyun.sms.version>2.0.23</aliyun.sms.version>
<tencent.sms.version>3.1.687</tencent.sms.version>
</properties>
<profiles>
@ -328,6 +330,12 @@
<version>${ruoyi-vue-plus.version}</version>
</dependency>
<dependency>
<groupId>com.github.gotson</groupId>
<artifactId>webp-imageio</artifactId>
<version>0.2.2</version>
</dependency>
</dependencies>
</dependencyManagement>

@ -114,7 +114,7 @@ public class SysProfileController extends BaseController {
if (!StringUtils.equalsAnyIgnoreCase(extension, MimeTypeUtils.IMAGE_EXTENSION)) {
return R.fail("文件格式不正确,请上传" + Arrays.toString(MimeTypeUtils.IMAGE_EXTENSION) + "格式");
}
SysOssVo oss = iSysOssService.upload(avatarfile);
SysOssVo oss = iSysOssService.uploadImgs(avatarfile,"avatar",200,200,null);
String avatar = oss.getUrl();
if (userService.updateUserAvatar(getUsername(), avatar)) {
ajax.put("imgUrl", avatar);

@ -7,6 +7,7 @@ package com.ruoyi.common.utils.file;
*/
public class MimeTypeUtils {
public static final String IMAGE_PNG = "image/png";
public static final String IMAGE_WEBP = "image/webp";
public static final String IMAGE_JPG = "image/jpg";
@ -16,7 +17,7 @@ public class MimeTypeUtils {
public static final String IMAGE_GIF = "image/gif";
public static final String[] IMAGE_EXTENSION = {"bmp", "gif", "jpg", "jpeg", "png"};
public static final String[] IMAGE_EXTENSION = {"bmp", "gif", "jpg", "jpeg", "png", "webp"};
public static final String[] FLASH_EXTENSION = {"swf", "flv"};
@ -27,7 +28,7 @@ public class MimeTypeUtils {
public static final String[] DEFAULT_ALLOWED_EXTENSION = {
// 图片
"bmp", "gif", "jpg", "jpeg", "png",
"bmp", "gif", "jpg", "jpeg", "png","webp",
// word excel powerpoint
"doc", "docx", "xls", "xlsx", "ppt", "pptx", "html", "htm", "txt",
// 压缩文件

@ -22,6 +22,7 @@ import com.ruoyi.oss.enumd.AccessPolicyType;
import com.ruoyi.oss.enumd.PolicyType;
import com.ruoyi.oss.exception.OssException;
import com.ruoyi.oss.properties.OssProperties;
import lombok.Getter;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
@ -38,6 +39,7 @@ public class OssClient {
private final String configKey;
@Getter
private final OssProperties properties;
private final AmazonS3 client;

@ -35,6 +35,11 @@
<artifactId>ruoyi-sms</artifactId>
</dependency>
<dependency>
<groupId>com.github.gotson</groupId>
<artifactId>webp-imageio</artifactId>
</dependency>
</dependencies>
</project>

@ -4,6 +4,7 @@ import com.ruoyi.common.core.domain.PageQuery;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.system.domain.SysConfig;
import java.awt.image.BufferedImage;
import java.util.List;
/**
@ -93,4 +94,9 @@ public interface ISysConfigService {
*/
boolean checkConfigKeyUnique(SysConfig config);
/**
*
* @return
*/
BufferedImage getWatermark();
}

@ -1,5 +1,7 @@
package com.ruoyi.system.service;
import cn.hutool.core.img.Img;
import cn.hutool.core.lang.UUID;
import com.ruoyi.common.core.domain.PageQuery;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.system.domain.SysOss;
@ -8,7 +10,13 @@ import com.ruoyi.system.domain.vo.SysOssVo;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletResponse;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Calendar;
import java.util.Collection;
import java.util.List;
@ -19,6 +27,8 @@ import java.util.List;
*/
public interface ISysOssService {
String IMAGE_WEBP="webp";
TableDataInfo<SysOssVo> queryPageList(SysOssBo sysOss, PageQuery pageQuery);
List<SysOssVo> listByIds(Collection<Long> ossIds);
@ -27,8 +37,201 @@ public interface ISysOssService {
SysOssVo upload(MultipartFile file);
/**
*
* @param file
* @param pre -
* @return
*/
SysOssVo upload(MultipartFile file,String pre);
/**
* 使
* @param file
* @param pre -
* @return
*/
SysOssVo uploadImgs(MultipartFile file,String pre);
/**
*
* @param file
* @param pre -
* @param maxWidth - 1
* @param maxHeight - 1
* @param watermark - null
* @return
*/
SysOssVo uploadImgs(MultipartFile file,String pre, int maxWidth, int maxHeight,
BufferedImage watermark);
void download(Long ossId, HttpServletResponse response) throws IOException;
Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid);
default InputStream formatImage(MultipartFile file, int maxWidth, int maxHeight,
BufferedImage watermark) {
try {
if (file == null || file.isEmpty()) {
throw new RuntimeException("上传图片不能为空");
}
if (!file.getContentType().startsWith("image/")) {
throw new RuntimeException("上传的文件不是图片");
}
return formatImage(file.getInputStream(), maxWidth, maxHeight, watermark);
} catch (IOException e) {
throw new RuntimeException("处理图片错误", e);
}
}
default InputStream formatImage(Image img, int maxWidth, int maxHeight, BufferedImage watermark) {
if (img == null) {
throw new RuntimeException("图片不能为空");
}
return formatImage(Img.from(img), maxWidth, maxHeight, watermark);
}
default InputStream formatImage(InputStream in, int maxWidth, int maxHeight, BufferedImage watermark) {
return formatImage(Img.from(in), maxWidth, maxHeight, watermark);
}
default InputStream formatImage(Img img, int maxWidth, int maxHeight, BufferedImage watermark) {
try {
int w = img.getImg().getWidth(null);
int h = img.getImg().getHeight(null);
if(maxWidth>0 && maxHeight > 0){
if (w > maxWidth || h > maxHeight) {
int outWidth = 0;
int outHeight = 0;
outHeight = maxWidth * h / w;
if (outHeight > maxHeight) {
outHeight = maxHeight;
outWidth = outHeight * maxWidth / h;
} else {
outWidth = maxWidth;
}
img = img.scale(outWidth, outHeight);
w = outWidth;
h = outHeight;
}
}
if (watermark != null) {
int ww = watermark.getWidth(null);
int wh = watermark.getHeight(null);
if (w > ww && h > wh) {
img = img.pressImage(watermark, 0, 0, 1f);
}
}
ByteArrayOutputStream pout = new ByteArrayOutputStream();
img.setTargetImageType(IMAGE_WEBP).write(pout);
ByteArrayInputStream pin = new ByteArrayInputStream(pout.toByteArray());
pout.close();
pout = null;
return pin;
} catch (Exception e) {
throw new RuntimeException("处理图片错误", e);
}
}
/**
* <pre>
* - URI
* -
* - {yyyy}/{MM}/{dd}/{HH}/{mm}/{ss}
* - {UUID} 32
* - {id} intid,+
* - {id16} intid16,+
* - {id36} intid36,+
* - {filename}
* - {ext}
* </pre>
*
* @param rule
* @param filename
* @return
*/
default String generateURI(String rule, String filename) {
Calendar c = Calendar.getInstance();
if (rule.contains("{yyyy}")) {
rule = rule.replace("{yyyy}", "" + c.get(Calendar.YEAR));
}
if (rule.contains("{MM}")) {
rule = rule.replace("{MM}", "" + (c.get(Calendar.MONTH) + 1));
}
if (rule.contains("{dd}")) {
rule = rule.replace("{dd}", "" + c.get(Calendar.DATE));
}
if (rule.contains("{HH}")) {
rule = rule.replace("{HH}", "" + c.get(Calendar.HOUR_OF_DAY));
}
if (rule.contains("{mm}")) {
rule = rule.replace("{mm}", "" + c.get(Calendar.MINUTE));
}
if (rule.contains("{ss}")) {
rule = rule.replace("{ss}", "" + c.get(Calendar.SECOND));
}
if (rule.contains("{UUID}")) {
rule = rule.replace("{UUID}", UUID.fastUUID().toString(true));
}
if (rule.contains("{id}")) {
rule = rule.replace("{id}", Integer.toString(id.nextId()));
}
if (rule.contains("{id16}")) {
rule = rule.replace("{id16}", Integer.toString(id.nextId(), 16));
}
if (rule.contains("{id36}")) {
rule = rule.replace("{id36}", Integer.toString(id.nextId(), 36));
}
if (rule.contains("{filename}")) {
String temp = null;
if (filename.contains(".")) {
temp = filename.substring(0, filename.lastIndexOf("."));
} else {
temp = filename;
}
rule = rule.replace("{filename}", temp);
}
if (rule.contains("{ext}")) {
String temp = null;
if (filename.contains(".")) {
temp = filename.substring(filename.lastIndexOf(".") + 1);
} else {
temp = "";
}
rule = rule.replace("{ext}", temp.toLowerCase());
}
return rule;
}
Id id = new Id();
static class Id {
private long lastTimestamp = 0;
private int sequence = 0;
public synchronized int nextId() {
long timestamp = System.currentTimeMillis();
if (lastTimestamp == timestamp) {
sequence = (sequence + 1) & 0xF;
if (sequence == 0) {
while (timestamp <= lastTimestamp) {
timestamp = System.currentTimeMillis();
}
}
} else {
sequence = 0;
}
lastTimestamp = timestamp;
return (int) (timestamp & 0xFFFF) << 8 | sequence;
}
}
}

@ -2,6 +2,8 @@ package com.ruoyi.system.service.impl;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpUtil;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
@ -18,10 +20,13 @@ import com.ruoyi.system.domain.SysConfig;
import com.ruoyi.system.mapper.SysConfigMapper;
import com.ruoyi.system.service.ISysConfigService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
@ -33,6 +38,7 @@ import java.util.Map;
*/
@RequiredArgsConstructor
@Service
@Slf4j
public class SysConfigServiceImpl implements ISysConfigService, ConfigService {
private final SysConfigMapper baseMapper;
@ -224,4 +230,24 @@ public class SysConfigServiceImpl implements ISysConfigService, ConfigService {
return SpringUtils.getAopProxy(this).selectConfigByKey(configKey);
}
private BufferedImage img;
@Override
public synchronized BufferedImage getWatermark() {
if (img == null) {
try{
HttpResponse response = HttpUtil.createGet(selectConfigByKey("image.watermark")).execute();
if(response.isOk()){
img = ImageIO.read(response.bodyStream());
}
log.info("下载默认水印图片成功");
}catch (Exception e) {
log.warn("下载水印图片失败",e);
}
}
return img;
}
}

@ -3,6 +3,7 @@ package com.ruoyi.system.service.impl;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
@ -23,6 +24,7 @@ import com.ruoyi.system.domain.SysOss;
import com.ruoyi.system.domain.bo.SysOssBo;
import com.ruoyi.system.domain.vo.SysOssVo;
import com.ruoyi.system.mapper.SysOssMapper;
import com.ruoyi.system.service.ISysConfigService;
import com.ruoyi.system.service.ISysOssService;
import lombok.RequiredArgsConstructor;
import org.springframework.cache.annotation.Cacheable;
@ -31,6 +33,7 @@ import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletResponse;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.InputStream;
import java.util.*;
@ -45,6 +48,7 @@ import java.util.stream.Collectors;
@Service
public class SysOssServiceImpl implements ISysOssService, OssService {
private final ISysConfigService configService;
private final SysOssMapper baseMapper;
@Override
@ -120,12 +124,65 @@ public class SysOssServiceImpl implements ISysOssService, OssService {
@Override
public SysOssVo upload(MultipartFile file) {
String originalfileName = file.getOriginalFilename();
String suffix = StringUtils.substring(originalfileName, originalfileName.lastIndexOf("."), originalfileName.length());
return upload(file,null);
}
@Override
public SysOssVo upload(MultipartFile file, String pre) {
String originalFileName = file.getOriginalFilename();
String suffix = StringUtils.substring(originalFileName, originalFileName.lastIndexOf("."), originalFileName.length());
OssClient storage = OssFactory.instance();
UploadResult uploadResult;
try {
uploadResult = storage.uploadSuffix(file.getBytes(), suffix, file.getContentType());
String path = "";
if(StrUtil.isNotBlank(storage.getProperties().getPrefix())){
path += storage.getProperties().getPrefix()+"/";
}
if(StrUtil.isNotBlank(pre)) {
path += pre+"/";
}
path += generateURI("{yyyy}/{MM}/{dd}/{id36}.{ext}",originalFileName);
uploadResult = storage.upload(file.getInputStream(),path,file.getContentType());
} catch (IOException e) {
throw new ServiceException(e.getMessage());
}
// 保存文件信息
SysOss oss = new SysOss();
oss.setUrl(uploadResult.getUrl());
oss.setFileSuffix(suffix);
oss.setFileName(uploadResult.getFilename());
oss.setOriginalName(originalFileName);
oss.setService(storage.getConfigKey());
baseMapper.insert(oss);
SysOssVo sysOssVo = new SysOssVo();
BeanCopyUtils.copy(oss, sysOssVo);
return this.matchingUrl(sysOssVo);
}
@Override
public SysOssVo uploadImgs(MultipartFile file, String pre) {
return uploadImgs(file,pre,Integer.valueOf(configService.selectConfigByKey("image.maxWidth")),Integer.valueOf(configService.selectConfigByKey("image.maxHeight")),configService.getWatermark());
}
@Override
public SysOssVo uploadImgs(MultipartFile file, String pre, int maxWidth, int maxHeight, BufferedImage watermark) {
String originalFileName = file.getOriginalFilename();
String suffix = StringUtils.substring(originalFileName, originalFileName.lastIndexOf("."), originalFileName.length());
OssClient storage = OssFactory.instance();
UploadResult uploadResult;
try (
InputStream in = formatImage(file,maxWidth,maxWidth,watermark)
){
String path = "";
if(StrUtil.isNotBlank(storage.getProperties().getPrefix())){
path += storage.getProperties().getPrefix()+"/";
}
if(StrUtil.isNotBlank(pre)) {
path += pre+"/";
}
path += generateURI("{yyyy}/{MM}/{dd}/{id36}.webp","a.webp");
uploadResult = storage.upload(in,path,"image/webp");
} catch (IOException e) {
throw new ServiceException(e.getMessage());
}
@ -134,7 +191,7 @@ public class SysOssServiceImpl implements ISysOssService, OssService {
oss.setUrl(uploadResult.getUrl());
oss.setFileSuffix(suffix);
oss.setFileName(uploadResult.getFilename());
oss.setOriginalName(originalfileName);
oss.setOriginalName(originalFileName);
oss.setService(storage.getConfigKey());
baseMapper.insert(oss);
SysOssVo sysOssVo = new SysOssVo();

Loading…
Cancel
Save