201 lines
7.7 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package edu.whut.smilepicturebackend.manager.upload;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.RandomUtil;
import com.qcloud.cos.model.PutObjectResult;
import com.qcloud.cos.model.ciModel.persistence.CIObject;
import com.qcloud.cos.model.ciModel.persistence.ImageInfo;
import com.qcloud.cos.model.ciModel.persistence.ProcessResults;
import edu.whut.smilepicturebackend.config.CosClientConfig;
import edu.whut.smilepicturebackend.exception.BusinessException;
import edu.whut.smilepicturebackend.exception.ErrorCode;
import edu.whut.smilepicturebackend.manager.CosManager;
import edu.whut.smilepicturebackend.model.file.UploadPictureResult;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import javax.annotation.Resource;
import java.io.File;
import java.util.Date;
import java.util.List;
/**
* 图片上传模板
*/
@Slf4j
public abstract class PictureUploadTemplate {
@Resource
private CosClientConfig cosClientConfig;
@Resource
private CosManager cosManager;
/**
* 上传图片
*
* @param inputSource 文件
* @param uploadPathPrefix 上传路径前缀
* @return
*/
public UploadPictureResult uploadPicture(Object inputSource, String uploadPathPrefix) {
// 1. 校验图片
validPicture(inputSource);
// 2. 图片上传地址
String uuid = RandomUtil.randomString(16);
String originalFilename = getOriginFilename(inputSource);
// extName 直接取扩展名,不含点
String extension = FileUtil.extName(originalFilename); // "png" 或 "jpg"
// 自己拼接文件上传路径,而不是使用原始文件名称,可以增强安全性
String uploadFilename = String.format("%s_%s.%s",
DateUtil.formatDate(new Date()),
uuid,
extension);
//如果多个项目共享存储桶,请在桶的根目录下以各项目名作为目录。
String projectName="smile-picture";
String uploadPath = String.format("/%s/%s/%s",projectName, uploadPathPrefix, uploadFilename);
File file = null;
try {
// 3. 创建临时文件,获取文件到服务器
file = File.createTempFile(uploadPath, null);
// 处理文件来源
processFile(inputSource, file);
// 4. 上传图片到对象存储
PutObjectResult putObjectResult = cosManager.putPictureObject(uploadPath, file);
// 5. 获取图片信息对象,封装返回结果
ImageInfo imageInfo = putObjectResult.getCiUploadResult().getOriginalInfo().getImageInfo();
// 获取到图片处理结果
ProcessResults processResults = putObjectResult.getCiUploadResult().getProcessResults();
List<CIObject> objectList = processResults.getObjectList();
if (CollUtil.isNotEmpty(objectList)) {
// 获取压缩之后得到的文件信息
CIObject compressedCiObject = objectList.get(0); //第一个是压缩后的
// 缩略图默认等于压缩图,压缩图是必有的
CIObject thumbnailCiObject = compressedCiObject;
// 有生成缩略图,才获取缩略图
if (objectList.size() > 1) { //第二个是缩略图
thumbnailCiObject = objectList.get(1);
}
// 封装压缩图的返回结果
return buildResult(originalFilename, compressedCiObject, thumbnailCiObject, imageInfo,uploadPath);
}
return buildResult(originalFilename, file, uploadPath, imageInfo);
} catch (Exception e) {
log.error("图片上传到对象存储失败", e);
throw new BusinessException(ErrorCode.SYSTEM_ERROR, "上传失败");
} finally {
// 6. 临时文件清理
this.deleteTempFile(file);
}
}
/**
* 校验输入源(本地文件或 URL
*/
protected abstract void validPicture(Object inputSource);
/**
* 获取输入源的原始文件名
*/
protected abstract String getOriginFilename(Object inputSource);
/**
* 处理输入源并生成本地临时文件
*/
protected abstract void processFile(Object inputSource, File file) throws Exception;
/**
* 封装返回结果
*
* @param originalFilename 原始文件名
* @param compressedCiObject 压缩后的对象
* @param thumbnailCiObject 缩略图对象
* @param imageInfo 图片信息
* @return
*/
private UploadPictureResult buildResult(String originalFilename, CIObject compressedCiObject, CIObject thumbnailCiObject,
ImageInfo imageInfo,String uploadPath) {
// 计算宽高
int picWidth = compressedCiObject.getWidth();
int picHeight = compressedCiObject.getHeight();
double picScale = NumberUtil.round(picWidth * 1.0 / picHeight, 2).doubleValue();
// 封装返回结果
UploadPictureResult uploadPictureResult = new UploadPictureResult();
// 设置压缩后的原图地址
uploadPictureResult.setUrl(cosClientConfig.getHost() + "/" + compressedCiObject.getKey());
uploadPictureResult.setName(FileUtil.mainName(originalFilename));
uploadPictureResult.setPicSize(compressedCiObject.getSize().longValue());
uploadPictureResult.setPicWidth(picWidth);
uploadPictureResult.setPicHeight(picHeight);
uploadPictureResult.setPicScale(picScale);
uploadPictureResult.setPicFormat(compressedCiObject.getFormat());
uploadPictureResult.setPicColor(imageInfo.getAve());
// 设置缩略图地址
uploadPictureResult.setThumbnailUrl(cosClientConfig.getHost() + "/" + thumbnailCiObject.getKey());
//设置原图地址
uploadPictureResult.setOriginalUrl(cosClientConfig.getHost() + "/" + uploadPath);
// 返回可访问的地址
return uploadPictureResult;
}
/**
* 封装返回结果
*
* @param originalFilename
* @param file
* @param uploadPath
* @param imageInfo 对象存储返回的图片信息
* @return
*/
private UploadPictureResult buildResult(String originalFilename, File file, String uploadPath, ImageInfo imageInfo) {
// 计算宽高
int picWidth = imageInfo.getWidth();
int picHeight = imageInfo.getHeight();
double picScale = NumberUtil.round(picWidth * 1.0 / picHeight, 2).doubleValue();
// 封装返回结果
UploadPictureResult uploadPictureResult = new UploadPictureResult();
uploadPictureResult.setUrl(cosClientConfig.getHost() + "/" + uploadPath);
uploadPictureResult.setName(FileUtil.mainName(originalFilename));
uploadPictureResult.setPicSize(FileUtil.size(file));
uploadPictureResult.setPicWidth(picWidth);
uploadPictureResult.setPicHeight(picHeight);
uploadPictureResult.setPicScale(picScale);
uploadPictureResult.setPicFormat(imageInfo.getFormat());
uploadPictureResult.setPicColor(imageInfo.getAve());
// 返回可访问的地址
return uploadPictureResult;
}
/**
* 清理临时文件
*
* @param file
*/
public void deleteTempFile(File file) {
if (file == null) {
return;
}
// 删除临时文件
boolean deleteResult = file.delete();
if (!deleteResult) {
log.error("file delete error, filepath = {}", file.getAbsolutePath());
}
}
}