You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

397 lines
12 KiB
Java

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

package com.ruoyi.system.service;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.img.Img;
import cn.hutool.core.lang.UUID;
import cn.hutool.core.util.HexUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.symmetric.SymmetricAlgorithm;
import cn.hutool.crypto.symmetric.SymmetricCrypto;
import com.ruoyi.common.core.domain.PageQuery;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.helper.DataPermissionHelper;
import com.ruoyi.common.utils.IdUtils;
import com.ruoyi.system.domain.SysOss;
import com.ruoyi.system.domain.bo.SysOssBo;
import com.ruoyi.system.domain.vo.SysOssVo;
import org.slf4j.LoggerFactory;
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.nio.ByteBuffer;
import java.util.Calendar;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.function.Supplier;
/**
* 文件上传 服务层
*
* @author Lion Li
*/
public interface ISysOssService {
/**
* 服务商
*/
public static enum Service {
minio, qiniu, aliyun, qcloud, image, upload;
}
String IMAGE_WEBP = "webp";
/**
* 默认路径前缀
*/
String PRE_DEFAULT = "default";
/**
* 设置指定服务商
*
* @param handle
*/
void setService(Service service, Runnable handle);
public <T> T setService(Service service, Supplier<T> handle);
/**
* 只保存,不存放记录
*
* @param handle 处理执行方法
*/
void ignore(Runnable handle);
/**
* 只保存,不存放记录
*
* @param handle 处理执行方法
*/
public <T> T ignore(Supplier<T> handle);
TableDataInfo<SysOssVo> queryPageList(SysOssBo sysOss, PageQuery pageQuery);
List<SysOssVo> listByIds(Collection<Long> ossIds);
SysOssVo getById(Long ossId);
default SysOssVo upload(MultipartFile file) {
return upload(file, PRE_DEFAULT);
}
/**
* @param file
* @param pre - 图片保存路径前缀
* @return
*/
default SysOssVo upload(MultipartFile file, String pre) {
if (file == null || file.isEmpty()) {
throw new RuntimeException("文件不能为空");
}
try {
return save(file.getInputStream(), file.getOriginalFilename(), file.getContentType(), pre);
} catch (IOException e) {
throw new RuntimeException(e.getMessage(), e);
}
}
/**
* 保存文件, rule:{yyyy}/{MM}/{dd}/{id36}.{ext}
*
* @param in 输入流
* @param filename 文件名
* @param contentType 文件类型
* @param pre 路径前缀
* @return
*/
default SysOssVo save(InputStream in, String filename, String contentType, String pre) {
return save(in, filename, contentType, pre, "{yyyy}/{MM}/{dd}/{id36}.{ext}");
}
/**
* 保存文件,保留文件名,rule:{yyyy}/{MM}/{dd}/{id36}/{filename}.{ext}
*
* @param in 输入流
* @param filename 文件名
* @param contentType 文件类型
* @param pre 路径前缀
* @return
*/
default SysOssVo saveFilename(InputStream in, String filename, String contentType, String pre) {
return save(in, filename, contentType, pre, "{yyyy}/{MM}/{dd}/{id36}/{filename}.{ext}");
}
/**
* 保存文件存放路径规则rule
* <pre>
* - 根据存放规则和文件名生成存放的URI
* - 支持
* - {yyyy}/{MM}/{dd}/{HH}/{mm}/{ss} 年月日时分秒
* - {UUID} 32位的唯一标志
* - {i} 自增id
* - {id} 当日int类型的唯一id,防止重复建议+年月日路径
* - {id16} 当日int类型的唯一id16进制表示,防止重复建议+年月日路径
* - {id36} 当日int类型的唯一id36进制表示,防止重复建议+年月日路径
* - {filename} 文件基础名称
* - {ext} 扩展名
* </pre>
*
* @param in 输入流
* @param filename 文件名
* @param contentType 文件类型
* @param pre 路径前缀
* @param rule 路径规则
* @return
*/
SysOssVo save(InputStream in, String filename, String contentType, String pre, String rule);
SysOssVo uploadImgs(MultipartFile file, String pre);
default SysOssVo uploadImgs(MultipartFile file, String pre, int maxWidth, int maxHeight, BufferedImage watermark) {
if (file == null || file.isEmpty()) {
throw new RuntimeException("图片不能为空");
}
try {
return uploadImgs(file.getInputStream(), pre, maxWidth, maxHeight, watermark);
} catch (IOException e) {
throw new RuntimeException(e.getMessage(), e);
}
}
/**
* @param in
* @param pre - 图片保存路径前缀
* @param maxWidth - 缩放到指定的宽 小于1表示不缩放
* @param maxHeight - 缩放到指定的高 小于1表示不缩放
* @param watermark - 水印图片 null表示不加水印
* @return
*/
SysOssVo uploadImgs(InputStream in, String pre, int maxWidth, int maxHeight,
BufferedImage watermark);
void download(Long ossId, HttpServletResponse response) throws IOException;
void download(String url, Service service, HttpServletResponse response) throws IOException;
InputStream download(Long ossId) throws IOException;
InputStream download(SysOssVo sysOss) throws IOException;
InputStream download(String url, Service service) 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 * w / 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位的唯一标志
* - {i} 自增id
* - {id} 当日int类型的唯一id,防止重复建议+年月日路径
* - {id16} 当日int类型的唯一id16进制表示,防止重复建议+年月日路径
* - {id36} 当日int类型的唯一id36进制表示,防止重复建议+年月日路径
* - {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}", String.format("%02d", c.get(Calendar.MONTH) + 1));
}
if (rule.contains("{dd}")) {
rule = rule.replace("{dd}", String.format("%02d", c.get(Calendar.DATE)));
}
if (rule.contains("{HH}")) {
rule = rule.replace("{HH}", String.format("%02d", c.get(Calendar.HOUR_OF_DAY)));
}
if (rule.contains("{mm}")) {
rule = rule.replace("{mm}", String.format("%02d", c.get(Calendar.MINUTE)));
}
if (rule.contains("{ss}")) {
rule = rule.replace("{ss}", String.format("%02d", c.get(Calendar.SECOND)));
}
if (rule.contains("{UUID}")) {
rule = rule.replace("{UUID}", UUID.fastUUID().toString(true));
}
if (rule.contains("{i}")) {
rule = rule.replace("{i}", IdUtils.nextId(Id.groupName).toString());
}
if (rule.contains("{id}")) {
rule = rule.replace("{id}", Long.toString(id.nextId()));
}
if (rule.contains("{id16}")) {
rule = rule.replace("{id16}", Long.toString(id.nextId(), 16));
}
if (rule.contains("{id36}")) {
rule = rule.replace("{id36}", Long.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 static final String groupName = "file:id";
private SymmetricCrypto crypto;
private String today = DateUtil.today();
public synchronized Long nextId() {
if (crypto == null || !today.equals(DateUtil.today())) {
today = DateUtil.today();
byte[] key = SecureUtil.generateKey(SymmetricAlgorithm.DES.getValue(), today.getBytes()).getEncoded();
crypto = new SymmetricCrypto(SymmetricAlgorithm.DES, key);
}
ByteBuffer buffer = ByteBuffer.allocate(Integer.BYTES);
buffer.putInt(IdUtils.nextDayId(groupName).intValue());
return Math.abs(ByteBuffer.wrap(crypto.encrypt(buffer.array())).getLong());
}
}
// public static void main(String[] args) {
// byte[] key = SecureUtil.generateKey(SymmetricAlgorithm.DES.getValue(),DateUtil.today().getBytes()).getEncoded();
// System.out.println(HexUtil.encodeHexStr(key));
//// byte[] key = HexUtil.decodeHex("a359f3fe88445c192f20d573c80af163");
// SymmetricCrypto aes = new SymmetricCrypto(SymmetricAlgorithm.DES, key);
//
//
// ByteBuffer buffer = ByteBuffer.allocate(Integer.BYTES);
//
// System.out.println(buffer.array().length);
// System.out.println(aes.encrypt(buffer.array()).length);
// buffer.clear();
// buffer.putInt(1);
// System.out.println(ByteBuffer.wrap(aes.encrypt(buffer.array())).getLong());
// buffer.clear();
// buffer.putInt(2);
// System.out.println(ByteBuffer.wrap(aes.encrypt(buffer.array())).getLong());
// buffer.clear();
// buffer.putInt(3);
// System.out.println(ByteBuffer.wrap(aes.encrypt(buffer.array())).getLong());
// }
SysOssVo url(SysOssVo oss, int second);
default SysOssVo url(SysOssVo oss) {
return url(oss, 120);
}
String url(Service service,String url,int second);
default String url(Service service,String url) {
return url(service,url, 120);
}
}