From 6927eabf279a7bbced3e2d135a24422b80383fd1 Mon Sep 17 00:00:00 2001 From: wangya <757914144@qq.com> Date: Fri, 26 Jul 2019 00:18:10 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E8=85=BE=E8=AE=AF=E4=BA=91os?= =?UTF-8?q?s=E5=8A=9F=E8=83=BD=EF=BC=9B=20=E8=A7=A3=E5=86=B3=E8=85=BE?= =?UTF-8?q?=E8=AE=AF=E4=BA=91jar=E5=8C=85=E4=B8=AD=E7=9A=84=E6=97=A5?= =?UTF-8?q?=E5=BF=97=E5=8C=85=E4=B8=8E=E9=A1=B9=E7=9B=AE=E7=9A=84=E6=97=A5?= =?UTF-8?q?=E5=BF=97=E5=8C=85=E5=86=B2=E7=AA=81=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 2 + .../handler/file/TencentYunFileHandler.java | 139 ++++++++++++++++++ .../halo/app/model/enums/AttachmentType.java | 7 +- .../properties/TencentYunProperties.java | 66 +++++++++ 4 files changed, 213 insertions(+), 1 deletion(-) create mode 100644 src/main/java/run/halo/app/handler/file/TencentYunFileHandler.java create mode 100644 src/main/java/run/halo/app/model/properties/TencentYunProperties.java diff --git a/build.gradle b/build.gradle index 01327f8dc..6b4ea8649 100644 --- a/build.gradle +++ b/build.gradle @@ -24,6 +24,7 @@ repositories { configurations { implementation { exclude module: 'spring-boot-starter-tomcat' + exclude module: 'slf4j-log4j12' } developmentOnly @@ -55,6 +56,7 @@ dependencies { implementation 'com.qiniu:qiniu-java-sdk:7.2.18' implementation 'com.aliyun.oss:aliyun-sdk-oss:3.4.2' implementation 'com.baidubce:bce-java-sdk:0.10.36' + implementation 'com.qcloud:cos_api:5.5.7' implementation 'net.coobird:thumbnailator:0.4.8' implementation 'io.springfox:springfox-swagger2:2.9.2' implementation 'io.springfox:springfox-swagger-ui:2.9.2' diff --git a/src/main/java/run/halo/app/handler/file/TencentYunFileHandler.java b/src/main/java/run/halo/app/handler/file/TencentYunFileHandler.java new file mode 100644 index 000000000..87b532c9b --- /dev/null +++ b/src/main/java/run/halo/app/handler/file/TencentYunFileHandler.java @@ -0,0 +1,139 @@ +package run.halo.app.handler.file; + + + +import com.qcloud.cos.COSClient; +import com.qcloud.cos.ClientConfig; +import com.qcloud.cos.auth.BasicCOSCredentials; +import com.qcloud.cos.auth.COSCredentials; +import com.qcloud.cos.model.ObjectMetadata; +import com.qcloud.cos.model.PutObjectResult; +import com.qcloud.cos.region.Region; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.http.MediaType; +import org.springframework.stereotype.Component; +import org.springframework.util.Assert; +import org.springframework.web.multipart.MultipartFile; +import run.halo.app.exception.FileOperationException; +import run.halo.app.model.enums.AttachmentType; +import run.halo.app.model.properties.TencentYunProperties; +import run.halo.app.model.support.UploadResult; +import run.halo.app.service.OptionService; +import run.halo.app.utils.FilenameUtils; + +import javax.imageio.ImageIO; +import java.awt.image.BufferedImage; +import java.util.Objects; + +/** + * TencentYun file handler. + * + * @author wangya + * @date 2019-07-25 + */ +@Slf4j +@Component +public class TencentYunFileHandler implements FileHandler { + + private final OptionService optionService; + + public TencentYunFileHandler(OptionService optionService) { + this.optionService = optionService; + } + + @Override + public UploadResult upload(MultipartFile file) { + Assert.notNull(file, "Multipart file must not be null"); + + // Get config + String ossRegion = optionService.getByPropertyOfNonNull(TencentYunProperties.OSS_REGION).toString(); + String ossAccessKey = optionService.getByPropertyOfNonNull(TencentYunProperties.OSS_ACCESS_KEY).toString(); + String ossAccessSecret = optionService.getByPropertyOfNonNull(TencentYunProperties.OSS_ACCESS_SECRET).toString(); + String ossBucketName = optionService.getByPropertyOfNonNull(TencentYunProperties.OSS_BUCKET_NAME).toString(); + String ossStyleRule = optionService.getByPropertyOfNonNull(TencentYunProperties.OSS_STYLE_RULE).toString(); + String ossSource = StringUtils.join("https://", ossBucketName, ".cos." + ossRegion+".myqcloud.com"); + + + COSCredentials cred = new BasicCOSCredentials(ossAccessKey, ossAccessSecret); + Region region = new Region(ossRegion); + ClientConfig clientConfig = new ClientConfig(region); + + + // Init OSS client + COSClient cosClient = new COSClient(cred, clientConfig); + + + + try { + String basename = FilenameUtils.getBasename(file.getOriginalFilename()); + String extension = FilenameUtils.getExtension(file.getOriginalFilename()); + String timestamp = String.valueOf(System.currentTimeMillis()); + String upFilePath = StringUtils.join(basename, "_", timestamp, ".", extension); + String filePath = StringUtils.join(StringUtils.appendIfMissing(ossSource, "/"), upFilePath); + + // Upload + ObjectMetadata objectMetadata = new ObjectMetadata(); + PutObjectResult putObjectResponseFromInputStream = cosClient.putObject(ossBucketName, upFilePath, file.getInputStream(),objectMetadata); + if (putObjectResponseFromInputStream == null) { + throw new FileOperationException("上传附件 " + file.getOriginalFilename() + " 到腾讯云失败 "); + } + + // Response result + UploadResult uploadResult = new UploadResult(); + uploadResult.setFilename(basename); + uploadResult.setFilePath(filePath); + uploadResult.setKey(upFilePath); + uploadResult.setMediaType(MediaType.valueOf(Objects.requireNonNull(file.getContentType()))); + uploadResult.setSuffix(extension); + uploadResult.setSize(file.getSize()); + + // Handle thumbnail + if (FileHandler.isImageType(uploadResult.getMediaType())) { + BufferedImage image = ImageIO.read(file.getInputStream()); + uploadResult.setWidth(image.getWidth()); + uploadResult.setHeight(image.getHeight()); + uploadResult.setThumbPath(StringUtils.isBlank(ossStyleRule) ? filePath : filePath + ossStyleRule); + } + + return uploadResult; + } catch (Exception e) { + throw new FileOperationException("附件 " + file.getOriginalFilename() + " 上传失败(腾讯云)", e); + } finally { + cosClient.shutdown(); + } + } + + @Override + public void delete(String key) { + Assert.notNull(key, "File key must not be blank"); + + // Get config + String ossRegion = optionService.getByPropertyOfNonNull(TencentYunProperties.OSS_REGION).toString(); + String ossAccessKey = optionService.getByPropertyOfNonNull(TencentYunProperties.OSS_ACCESS_KEY).toString(); + String ossAccessSecret = optionService.getByPropertyOfNonNull(TencentYunProperties.OSS_ACCESS_SECRET).toString(); + String ossBucketName = optionService.getByPropertyOfNonNull(TencentYunProperties.OSS_BUCKET_NAME).toString(); + String ossSource = StringUtils.join("https://", ossBucketName, ".cos." + ossRegion+".myqcloud.com"); + + COSCredentials cred = new BasicCOSCredentials(ossAccessKey, ossAccessSecret); + Region region = new Region(ossRegion); + ClientConfig clientConfig = new ClientConfig(region); + + + // Init OSS client + COSClient cosClient = new COSClient(cred, clientConfig); + + try { + cosClient.deleteObject(ossBucketName, key); + } catch (Exception e) { + throw new FileOperationException("附件 " + key + " 从腾讯云删除失败", e); + } finally { + cosClient.shutdown(); + } + } + + @Override + public boolean supportType(AttachmentType type) { + return AttachmentType.TENCENTYUN.equals(type); + } +} diff --git a/src/main/java/run/halo/app/model/enums/AttachmentType.java b/src/main/java/run/halo/app/model/enums/AttachmentType.java index 59fdd6482..47942a8f7 100644 --- a/src/main/java/run/halo/app/model/enums/AttachmentType.java +++ b/src/main/java/run/halo/app/model/enums/AttachmentType.java @@ -36,7 +36,12 @@ public enum AttachmentType implements ValueEnum { /** * 百度云 */ - BAIDUYUN(5); + BAIDUYUN(5), + + /** + * 腾讯云 + */ + TENCENTYUN(6); private Integer value; diff --git a/src/main/java/run/halo/app/model/properties/TencentYunProperties.java b/src/main/java/run/halo/app/model/properties/TencentYunProperties.java new file mode 100644 index 000000000..32a5b0058 --- /dev/null +++ b/src/main/java/run/halo/app/model/properties/TencentYunProperties.java @@ -0,0 +1,66 @@ +package run.halo.app.model.properties; + +/** + * TencentYun properties. + * + * @author wangya + * @date 2019-07-25 + */ +public enum TencentYunProperties implements PropertyEnum { + + /** + * Tencentyun oss endpoint. + */ + OSS_REGION("oss_tencentyun_region", String.class, ""), + + /** + * Tencentyun oss bucket name. + */ + OSS_BUCKET_NAME("oss_tencentyun_bucket_name", String.class, ""), + + /** + * Tencentyun oss access key. + */ + OSS_ACCESS_KEY("oss_tencentyun_access_key", String.class, ""), + + /** + * Tencentyun oss access secret. + */ + OSS_ACCESS_SECRET("oss_tencentyun_access_secret", String.class, ""), + + /** + * Tencentyun oss style rule + */ + OSS_STYLE_RULE("oss_tencentyun_style_rule", String.class, ""); + + private final String value; + + private final Class type; + + private final String defaultValue; + + TencentYunProperties(String value, Class type, String defaultValue) { + this.defaultValue = defaultValue; + if (!PropertyEnum.isSupportedType(type)) { + throw new IllegalArgumentException("Unsupported blog property type: " + type); + } + + this.value = value; + this.type = type; + } + + @Override + public Class getType() { + return type; + } + + @Override + public String defaultValue() { + return defaultValue; + } + + @Override + public String getValue() { + return value; + } +}