diff --git a/pom.xml b/pom.xml index 639f1e815..cbd643638 100755 --- a/pom.xml +++ b/pom.xml @@ -45,6 +45,7 @@ 4.5.0 4.0.1 7.2.18 + 3.4.2 0.4.8 0.12.1 3.8.1 @@ -171,6 +172,13 @@ + + + com.aliyun.oss + aliyun-sdk-oss + ${aliyun-java-sdk.version} + + net.coobird diff --git a/src/main/java/run/halo/app/handler/file/AliYunFileHandler.java b/src/main/java/run/halo/app/handler/file/AliYunFileHandler.java new file mode 100644 index 000000000..3fce783f8 --- /dev/null +++ b/src/main/java/run/halo/app/handler/file/AliYunFileHandler.java @@ -0,0 +1,125 @@ +package run.halo.app.handler.file; + +import cn.hutool.core.lang.Assert; +import com.aliyun.oss.OSS; +import com.aliyun.oss.OSSClientBuilder; +import com.aliyun.oss.model.*; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.http.MediaType; +import org.springframework.stereotype.Component; +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.AliYunProperties; +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.Date; +import java.util.Objects; + +/** + * AliYun file handler. + * @author MyFaith + * @date 2019-04-04 00:06:13 + */ +@Slf4j +@Component +public class AliYunFileHandler implements FileHandler { + + private final OptionService optionService; + + public AliYunFileHandler(OptionService optionService) { + this.optionService = optionService; + } + + @Override + public UploadResult upload(MultipartFile file) { + Assert.notNull(file, "Multipart file must not be null"); + + // Get config + String ossEndPoint = optionService.getByPropertyOfNonNull(AliYunProperties.OSS_ENDPOINT); + String ossAccessKey = optionService.getByPropertyOfNonNull(AliYunProperties.OSS_ACCESS_KEY); + String ossAccessSecret = optionService.getByPropertyOfNonNull(AliYunProperties.OSS_ACCESS_SECRET); + String ossBucketName = optionService.getByPropertyOfNonNull(AliYunProperties.OSS_BUCKET_NAME); + String ossSource = StringUtils.join("https://", ossBucketName, "." + ossEndPoint); + + // Init OSS client + OSS ossClient = new OSSClientBuilder().build(ossEndPoint, ossAccessKey, ossAccessSecret); + + try { + String basename = FilenameUtils.getBasename(file.getOriginalFilename()); + String extension = FilenameUtils.getExtension(file.getOriginalFilename()); + String timestamp = String.valueOf(new Date().getTime()); + String upFilePath = StringUtils.join(basename, "_", timestamp, ".", extension); + String filePath = StringUtils.join(StringUtils.appendIfMissing(ossSource, "/"), upFilePath); + + // Upload + PutObjectResult putObjectResult = ossClient.putObject(ossBucketName, upFilePath, file.getInputStream()); + if (putObjectResult == null) { + throw new FileOperationException("Failed to upload file " + file.getOriginalFilename() + " to AliYun " + upFilePath); + } + + // 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(filePath); + } + + return uploadResult; + } catch (Exception e){ + e.printStackTrace(); + } finally { + ossClient.shutdown(); + } + + // Build result + UploadResult result = new UploadResult(); + + log.info("File: [{}] uploaded successfully", file.getOriginalFilename()); + + return result; + } + + @Override + public void delete(String key) { + Assert.notNull(key, "File key must not be blank"); + + // Get config + String ossEndPoint = optionService.getByPropertyOfNonNull(AliYunProperties.OSS_ENDPOINT); + String ossAccessKey = optionService.getByPropertyOfNonNull(AliYunProperties.OSS_ACCESS_KEY); + String ossAccessSecret = optionService.getByPropertyOfNonNull(AliYunProperties.OSS_ACCESS_SECRET); + String ossBucketName = optionService.getByPropertyOfNonNull(AliYunProperties.OSS_BUCKET_NAME); + String ossSource = StringUtils.join("https://", ossBucketName, "." + ossEndPoint); + + // Init OSS client + OSS ossClient = new OSSClientBuilder().build(ossEndPoint, ossAccessKey, ossAccessSecret); + + try { + ossClient.deleteObject(new DeleteObjectsRequest(ossBucketName).withKey(key)); + } catch (Exception e) { + throw new FileOperationException("Failed to delete file " + key + " from AliYun", e); + } finally { + ossClient.shutdown(); + } + } + + @Override + public boolean supportType(AttachmentType type) { + return AttachmentType.ALIYUN.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 fb70ed88e..d2e1c7a5d 100644 --- a/src/main/java/run/halo/app/model/enums/AttachmentType.java +++ b/src/main/java/run/halo/app/model/enums/AttachmentType.java @@ -26,7 +26,12 @@ public enum AttachmentType implements ValueEnum { /** * sm.ms */ - SMMS(3); + SMMS(3), + + /** + * 阿里云 + */ + ALIYUN(4); private Integer value; diff --git a/src/main/java/run/halo/app/model/properties/AliYunProperties.java b/src/main/java/run/halo/app/model/properties/AliYunProperties.java new file mode 100644 index 000000000..c12d3edba --- /dev/null +++ b/src/main/java/run/halo/app/model/properties/AliYunProperties.java @@ -0,0 +1,35 @@ +package run.halo.app.model.properties; + +/** + * AliYun properties. + * @author MyFaith + * @date 2019-04-04 00:00:56 + */ +public enum AliYunProperties implements PropertyEnum { + OSS_ENDPOINT("oss_aliyun_endpoint", String.class), + OSS_BUCKET_NAME("oss_aliyun_bucket_name", String.class), + OSS_ACCESS_KEY("oss_aliyun_access_key", String.class), + OSS_ACCESS_SECRET("oss_aliyun_access_secret", String.class); + + private String value; + private Class type; + + AliYunProperties(String value, Class type) { + 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 getValue() { + return value; + } +}