¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, Chill Zhuang All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: Chill åºéª (smallchill@163.com) |
| | | */ |
| | | package org.springblade.core.oss; |
| | | |
| | | import com.aliyun.oss.OSSClient; |
| | | import com.aliyun.oss.common.utils.BinaryUtil; |
| | | import com.aliyun.oss.model.MatchMode; |
| | | import com.aliyun.oss.model.ObjectMetadata; |
| | | import com.aliyun.oss.model.PolicyConditions; |
| | | import com.aliyun.oss.model.PutObjectResult; |
| | | import lombok.AllArgsConstructor; |
| | | import lombok.SneakyThrows; |
| | | import org.springblade.core.oss.model.BladeFile; |
| | | import org.springblade.core.oss.model.OssFile; |
| | | import org.springblade.core.oss.props.OssProperties; |
| | | import org.springblade.core.oss.rule.OssRule; |
| | | import org.springblade.core.tool.jackson.JsonUtil; |
| | | import org.springblade.core.tool.utils.StringPool; |
| | | import org.springframework.util.StringUtils; |
| | | import org.springframework.web.multipart.MultipartFile; |
| | | |
| | | import java.io.InputStream; |
| | | import java.nio.charset.StandardCharsets; |
| | | import java.util.Date; |
| | | import java.util.LinkedHashMap; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | |
| | | /** |
| | | * AliossTemplate |
| | | * |
| | | * @author Chill |
| | | */ |
| | | @AllArgsConstructor |
| | | public class AliossTemplate implements OssTemplate { |
| | | private final OSSClient ossClient; |
| | | private final OssProperties ossProperties; |
| | | private final OssRule ossRule; |
| | | |
| | | @Override |
| | | @SneakyThrows |
| | | public void makeBucket(String bucketName) { |
| | | if (!bucketExists(bucketName)) { |
| | | ossClient.createBucket(getBucketName(bucketName)); |
| | | } |
| | | } |
| | | |
| | | @Override |
| | | @SneakyThrows |
| | | public void removeBucket(String bucketName) { |
| | | ossClient.deleteBucket(getBucketName(bucketName)); |
| | | } |
| | | |
| | | @Override |
| | | @SneakyThrows |
| | | public boolean bucketExists(String bucketName) { |
| | | return ossClient.doesBucketExist(getBucketName(bucketName)); |
| | | } |
| | | |
| | | @Override |
| | | @SneakyThrows |
| | | public void copyFile(String bucketName, String fileName, String destBucketName) { |
| | | ossClient.copyObject(getBucketName(bucketName), fileName, getBucketName(destBucketName), fileName); |
| | | } |
| | | |
| | | @Override |
| | | @SneakyThrows |
| | | public void copyFile(String bucketName, String fileName, String destBucketName, String destFileName) { |
| | | ossClient.copyObject(getBucketName(bucketName), fileName, getBucketName(destBucketName), destFileName); |
| | | } |
| | | |
| | | @Override |
| | | @SneakyThrows |
| | | public OssFile statFile(String fileName) { |
| | | return statFile(ossProperties.getBucketName(), fileName); |
| | | } |
| | | |
| | | @Override |
| | | @SneakyThrows |
| | | public OssFile statFile(String bucketName, String fileName) { |
| | | ObjectMetadata stat = ossClient.getObjectMetadata(getBucketName(bucketName), fileName); |
| | | OssFile ossFile = new OssFile(); |
| | | ossFile.setName(fileName); |
| | | ossFile.setLink(fileLink(ossFile.getName())); |
| | | ossFile.setHash(stat.getContentMD5()); |
| | | ossFile.setLength(stat.getContentLength()); |
| | | ossFile.setPutTime(stat.getLastModified()); |
| | | ossFile.setContentType(stat.getContentType()); |
| | | return ossFile; |
| | | } |
| | | |
| | | @Override |
| | | @SneakyThrows |
| | | public String filePath(String fileName) { |
| | | return getOssHost().concat(StringPool.SLASH).concat(fileName); |
| | | } |
| | | |
| | | @Override |
| | | @SneakyThrows |
| | | public String filePath(String bucketName, String fileName) { |
| | | return getOssHost(bucketName).concat(StringPool.SLASH).concat(fileName); |
| | | } |
| | | |
| | | @Override |
| | | @SneakyThrows |
| | | public String fileLink(String fileName) { |
| | | return getOssHost().concat(StringPool.SLASH).concat(fileName); |
| | | } |
| | | |
| | | @Override |
| | | @SneakyThrows |
| | | public String fileLink(String bucketName, String fileName) { |
| | | return getOssHost(bucketName).concat(StringPool.SLASH).concat(fileName); |
| | | } |
| | | |
| | | /** |
| | | * æä»¶å¯¹è±¡ |
| | | * |
| | | * @param file ä¸ä¼ æä»¶ç±» |
| | | * @return |
| | | */ |
| | | @Override |
| | | @SneakyThrows |
| | | public BladeFile putFile(MultipartFile file) { |
| | | return putFile(ossProperties.getBucketName(), file.getOriginalFilename(), file); |
| | | } |
| | | |
| | | /** |
| | | * @param fileName ä¸ä¼ æä»¶å |
| | | * @param file ä¸ä¼ æä»¶ç±» |
| | | * @return |
| | | */ |
| | | @Override |
| | | @SneakyThrows |
| | | public BladeFile putFile(String fileName, MultipartFile file) { |
| | | return putFile(ossProperties.getBucketName(), fileName, file); |
| | | } |
| | | |
| | | @Override |
| | | @SneakyThrows |
| | | public BladeFile putFile(String bucketName, String fileName, MultipartFile file) { |
| | | return putFile(bucketName, fileName, file.getInputStream()); |
| | | } |
| | | |
| | | @Override |
| | | @SneakyThrows |
| | | public BladeFile putFile(String fileName, InputStream stream) { |
| | | return putFile(ossProperties.getBucketName(), fileName, stream); |
| | | } |
| | | |
| | | @Override |
| | | @SneakyThrows |
| | | public BladeFile putFile(String bucketName, String fileName, InputStream stream) { |
| | | return put(bucketName, stream, fileName, false); |
| | | } |
| | | |
| | | @SneakyThrows |
| | | public BladeFile put(String bucketName, InputStream stream, String key, boolean cover) { |
| | | makeBucket(bucketName); |
| | | String originalName = key; |
| | | key = getFileName(key); |
| | | // è¦çä¸ä¼ |
| | | if (cover) { |
| | | ossClient.putObject(getBucketName(bucketName), key, stream); |
| | | } else { |
| | | PutObjectResult response = ossClient.putObject(getBucketName(bucketName), key, stream); |
| | | int retry = 0; |
| | | int retryCount = 5; |
| | | while (StringUtils.isEmpty(response.getETag()) && retry < retryCount) { |
| | | response = ossClient.putObject(getBucketName(bucketName), key, stream); |
| | | retry++; |
| | | } |
| | | } |
| | | BladeFile file = new BladeFile(); |
| | | file.setOriginalName(originalName); |
| | | file.setName(key); |
| | | file.setDomain(getOssHost(bucketName)); |
| | | file.setLink(fileLink(bucketName, key)); |
| | | return file; |
| | | } |
| | | |
| | | @Override |
| | | @SneakyThrows |
| | | public void removeFile(String fileName) { |
| | | ossClient.deleteObject(getBucketName(), fileName); |
| | | } |
| | | |
| | | @Override |
| | | @SneakyThrows |
| | | public void removeFile(String bucketName, String fileName) { |
| | | ossClient.deleteObject(getBucketName(bucketName), fileName); |
| | | } |
| | | |
| | | @Override |
| | | @SneakyThrows |
| | | public void removeFiles(List<String> fileNames) { |
| | | fileNames.forEach(this::removeFile); |
| | | } |
| | | |
| | | @Override |
| | | @SneakyThrows |
| | | public void removeFiles(String bucketName, List<String> fileNames) { |
| | | fileNames.forEach(fileName -> removeFile(getBucketName(bucketName), fileName)); |
| | | } |
| | | |
| | | /** |
| | | * æ ¹æ®è§åçæå卿¡¶åç§°è§å |
| | | * |
| | | * @return String |
| | | */ |
| | | private String getBucketName() { |
| | | return getBucketName(ossProperties.getBucketName()); |
| | | } |
| | | |
| | | /** |
| | | * æ ¹æ®è§åçæå卿¡¶åç§°è§å |
| | | * |
| | | * @param bucketName å卿¡¶åç§° |
| | | * @return String |
| | | */ |
| | | private String getBucketName(String bucketName) { |
| | | return ossRule.bucketName(bucketName); |
| | | } |
| | | |
| | | /** |
| | | * æ ¹æ®è§åçææä»¶åç§°è§å |
| | | * |
| | | * @param originalFilename åå§æä»¶å |
| | | * @return string |
| | | */ |
| | | private String getFileName(String originalFilename) { |
| | | return ossRule.fileName(originalFilename); |
| | | } |
| | | |
| | | public String getUploadToken() { |
| | | return getUploadToken(ossProperties.getBucketName()); |
| | | } |
| | | |
| | | /** |
| | | * TODO è¿ææ¶é´ |
| | | * <p> |
| | | * è·åä¸ä¼ åè¯ï¼æ®éä¸ä¼ |
| | | */ |
| | | public String getUploadToken(String bucketName) { |
| | | // é»è®¤è¿ææ¶é´2å°æ¶ |
| | | return getUploadToken(bucketName, ossProperties.getArgs().get("expireTime", 3600L)); |
| | | } |
| | | |
| | | /** |
| | | * TODO ä¸ä¼ 大å°éå¶ãåºç¡è·¯å¾ |
| | | * <p> |
| | | * è·åä¸ä¼ åè¯ï¼æ®éä¸ä¼ |
| | | */ |
| | | public String getUploadToken(String bucketName, long expireTime) { |
| | | String baseDir = "upload"; |
| | | |
| | | long expireEndTime = System.currentTimeMillis() + expireTime * 1000; |
| | | Date expiration = new Date(expireEndTime); |
| | | |
| | | PolicyConditions policyConds = new PolicyConditions(); |
| | | // é»è®¤å¤§å°éå¶10M |
| | | policyConds.addConditionItem(PolicyConditions.COND_CONTENT_LENGTH_RANGE, 0, ossProperties.getArgs().get("contentLengthRange", 10485760)); |
| | | policyConds.addConditionItem(MatchMode.StartWith, PolicyConditions.COND_KEY, baseDir); |
| | | |
| | | String postPolicy = ossClient.generatePostPolicy(expiration, policyConds); |
| | | byte[] binaryData = postPolicy.getBytes(StandardCharsets.UTF_8); |
| | | String encodedPolicy = BinaryUtil.toBase64String(binaryData); |
| | | String postSignature = ossClient.calculatePostSignature(postPolicy); |
| | | |
| | | Map<String, String> respMap = new LinkedHashMap<>(16); |
| | | respMap.put("accessid", ossProperties.getAccessKey()); |
| | | respMap.put("policy", encodedPolicy); |
| | | respMap.put("signature", postSignature); |
| | | respMap.put("dir", baseDir); |
| | | respMap.put("host", getOssHost(bucketName)); |
| | | respMap.put("expire", String.valueOf(expireEndTime / 1000)); |
| | | return JsonUtil.toJson(respMap); |
| | | } |
| | | |
| | | /** |
| | | * è·ååå |
| | | * |
| | | * @param bucketName å卿¡¶åç§° |
| | | * @return String |
| | | */ |
| | | public String getOssHost(String bucketName) { |
| | | String prefix = ossProperties.getEndpoint().contains("https://") ? "https://" : "http://"; |
| | | return prefix + getBucketName(bucketName) + StringPool.DOT + ossProperties.getEndpoint().replaceFirst(prefix, StringPool.EMPTY); |
| | | } |
| | | |
| | | /** |
| | | * è·ååå |
| | | * |
| | | * @return String |
| | | */ |
| | | public String getOssHost() { |
| | | return getOssHost(ossProperties.getBucketName()); |
| | | } |
| | | |
| | | } |