本文为上一篇minio使用的衍生版
相关链接:1.https://www.cnblogs.com/ComfortableM/p/18286363
2.https://blog.csdn.net/zizai_a/article/details/140796186?spm=1001.2014.3001.5501
云存储已经成为现代信息技术不可或缺的一部分,它为企业和个人提供了诸多便利。以下是几个关键点,说明云存储为何如此重要:
1. 数据安全与备份
2. 成本效益
3. 灵活性与可扩展性
4. 访问与协作
5. 灾难恢复
6. 技术创新与支持
7. 法规遵从
8. 对智慧城市的贡献
综上所述,云存储不仅改变了企业和个人管理数据的方式,还推动了整个社会向着更加高效、可持续的方向发展。随着技术的进步,我们可以期待云存储在未来扮演更加重要的角色。
Amazon Simple Storage Service (S3) 是 Amazon Web Services (AWS) 中最成熟且广泛使用的对象存储服务之一。自从2006年推出以来,S3 已经成为云计算领域的一个标志性产品,它不仅为AWS奠定了基础,而且在全球范围内成为了云存储的标准之一。
关键点:
Amazon S3 作为 AWS 的旗舰级服务之一,在过去十几年里已经成为了全球云存储领域的标杆。无论是从成熟度、可靠性还是功能丰富性来看,S3 都是企业和开发者信赖的选择。随着 AWS 继续在其基础上进行创新和发展,我们有理由相信 S3 将继续引领云存储的发展趋势。
Amazon Simple Storage Service (S3) 是亚马逊 Web Services (AWS) 提供的一种对象存储服务。自2006年推出以来,S3 已经成为了云存储领域的一个标志性产品,它为开发者和企业提供了一种简单、高效的方式来存储和检索任意数量的数据。
核心特点:
使用场景:
注册账户:https://signin.aws.amazon.com/signup?request_type=register
S3具有很多免费使用的套餐,可以为开发前搭建一个小型测试环境。
注册成功后登录进控制台,点击右上角用户有一个安全凭证:
下滑到访问密钥这,创建一个访问密钥,这个是连接S3的凭证。也可以创建一个IAM账户,为其分配权限,用IAM账户登录到控制台来创建访问密钥,S3也建议这样做。
接下来可以通过左上角服务找到S3自由发挥了。
<dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>s3</artifactId>
</dependency>
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import software.amazon.awssdk.auth.credentials.AwsBasicCredentials;
import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.s3.S3Client;
import software.amazon.awssdk.services.s3.S3Configuration;
import software.amazon.awssdk.services.s3.presigner.S3Presigner;
import java.net.URI;
@Configuration
public class AmazonS3Config {
@Value("${aws.s3.accessKey}")
private String accessKeyId;
@Value("${aws.s3.secretKey}")
private String secretKey;
@Value("${aws.s3.endPoint}")
private String endPoint;//接入点,未设置可以注释
@Bean
public S3Client s3Client() {
AwsBasicCredentials credentials = AwsBasicCredentials.create(accessKeyId, secretKey);
return S3Client.builder()
.credentialsProvider(StaticCredentialsProvider.create(credentials))
.region(Region.US_EAST_1)//区域
.endpointOverride(URI.create(endPoint))//接入点
.serviceConfiguration(S3Configuration.builder()
.pathStyleAccessEnabled(true)
.chunkedEncodingEnabled(false)
.build())
.build();
}
//S3Presigner是用来获取文件对象预签名url的
@Bean
public S3Presigner s3Presigner() {
AwsBasicCredentials credentials = AwsBasicCredentials.create(accessKeyId, secretKey);
return S3Presigner.builder()
.credentialsProvider(StaticCredentialsProvider.create(credentials))
.region(Region.US_EAST_1)
.endpointOverride(URI.create(endPoint))
.build();
}
}
public boolean ifExistsBucket(String bucketName) {
// 尝试发送 HEAD 请求来检查存储桶是否存在
try {
HeadBucketResponse headBucketResponse = s3Client.headBucket(HeadBucketRequest.builder().bucket(bucketName).build());
} catch (S3Exception e) {
// 如果捕获到 S3 异常且状态码为 404,则说明存储桶不存在
if (e.statusCode() == 404) {
return false;
} else {
// 打印异常堆栈跟踪
e.printStackTrace();
}
}
// 如果没有抛出异常或状态码不是 404,则说明存储桶存在
return true;
}
public boolean createBucket(String bucketName) throws RuntimeException {
// 检查存储桶是否已经存在
if (ifExistsBucket(bucketName)) {
// 如果存储桶已存在,则抛出运行时异常
throw new RuntimeException("桶已存在");
}
// 创建新的存储桶
S3Response bucket = s3Client.createBucket(CreateBucketRequest.builder().bucket(bucketName).build());
// 检查存储桶是否创建成功
return ifExistsBucket(bucketName);
}
public boolean removeBucket(String bucketName) {
// 如果存储桶不存在,则直接返回 true
if (!ifExistsBucket(bucketName)) {
return true;
}
// 删除存储桶
s3Client.deleteBucket(DeleteBucketRequest.builder().bucket(bucketName).build());
// 检查存储桶是否已被删除
return !ifExistsBucket(bucketName);
}
public boolean uploadObject(String bucketName, String targetObject, String sourcePath) {
// 尝试上传本地文件到指定的存储桶和对象键
try {
s3Client.putObject(PutObjectRequest.builder()
.bucket(bucketName)
.key(targetObject)
.build(), RequestBody.fromFile(new File(sourcePath)));
} catch (Exception e) {
// 如果出现异常,则打印异常堆栈跟踪并返回 false
e.printStackTrace();
return false;
}
// 如果上传成功则返回 true
return true;
}
public boolean putObject(String bucketName, String object, InputStream inputStream, long size) {
// 尝试从输入流上传数据到指定的存储桶和对象键
try {
s3Client.putObject(PutObjectRequest.builder()
.bucket(bucketName)
.key(object)
.build(), RequestBody.fromInputStream(inputStream, size));
} catch (Exception e) {
// 如果出现异常,则打印异常堆栈跟踪并返回 false
e.printStackTrace();
return false;
}
// 如果上传成功则返回 true
return true;
}
public boolean putObject(String bucketName, String object, InputStream inputStream, long size, Map<String, String> tags) {
// 尝试从输入流上传数据到指定的存储桶和对象键,并设置标签
try {
// 将标签映射转换为标签集合
Collection<Tag> tagList = tags.entrySet().stream().map(entry ->
Tag.builder().key(entry.getKey()).value(entry.getValue()).build())
.collect(Collectors.toList());
// 上传对象并设置标签
s3Client.putObject(PutObjectRequest.builder()
.bucket(bucketName)
.key(object)
.tagging(Tagging.builder()
.tagSet(tagList)
.build())
.build(), RequestBody.fromInputStream(inputStream, size));
} catch (Exception e) {
// 如果出现异常,则打印异常堆栈跟踪并返回 false
e.printStackTrace();
return false;
}
// 如果上传成功则返回 true
return true;
}
import software.amazon.awssdk.services.s3.S3Client;
import software.amazon.awssdk.services.s3.model.*;
import software.amazon.awssdk.core.sync.RequestBody;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
public class S3MultipartUploader {
private static final S3Client s3Client = S3Client.create();
/**
* 开始一个新的分片上传会话。
*
* @param bucketName 存储桶名称
* @param objectKey 对象键
* @return 返回的 UploadId 用于后续操作
*/
public static InitiateMultipartUploadResponse initiateMultipartUpload(String bucketName, String objectKey) {
InitiateMultipartUploadRequest request = InitiateMultipartUploadRequest.builder()
.bucket(bucketName)
.key(objectKey)
.build();
return s3Client.initiateMultipartUpload(request);
}
/**
* 上传一个分片。
*
* @param bucketName 存储桶名称
* @param objectKey 对象键
* @param uploadId 上传会话的 ID
* @param partNumber 分片序号
* @param file 文件
* @param offset 文件偏移量
* @param length 文件长度
* @return 返回的 Part ETag 用于完成上传时验证
*/
public static UploadPartResponse uploadPart(String bucketName, String objectKey, String uploadId,
int partNumber, File file, long offset, long length) {
try (FileInputStream fis = new FileInputStream(file)) {
UploadPartRequest request = UploadPartRequest.builder()
.bucket(bucketName)
.key(objectKey)
.uploadId(uploadId)
.partNumber(partNumber)
.build();
RequestBody requestBody = RequestBody.fromInputStream(fis, length, offset);
return s3Client.uploadPart(request, requestBody);
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
/**
* 完成分片上传。
*
* @param bucketName 存储桶名称
* @param objectKey 对象键
* @param uploadId 上传会话的 ID
* @param parts 已上传的分片列表
*/
public static CompleteMultipartUploadResponse completeMultipartUpload(String bucketName, String objectKey,
String uploadId, List<CompletedPart> parts) {
CompleteMultipartUploadRequest request = CompleteMultipartUploadRequest.builder()
.bucket(bucketName)
.key(objectKey)
.uploadId(uploadId)
.multipartUpload(CompletedMultipartUpload.builder()
.parts(parts)
.build())
.build();
return s3Client.completeMultipartUpload(request);
}
/**
* 取消分片上传会话。
*
* @param bucketName 存储桶名称
* @param objectKey 对象键
* @param uploadId 上传会话的 ID
*/
public static void abortMultipartUpload(String bucketName, String objectKey, String uploadId) {
AbortMultipartUploadRequest request = AbortMultipartUploadRequest.builder()
.bucket(bucketName)
.key(objectKey)
.uploadId(uploadId)
.build();
s3Client.abortMultipartUpload(request);
}
public static void main(String[] args) {
String bucketName = "your-bucket-name";
String objectKey = "path/to/your-object";
File fileToUpload = new File("path/to/your/local/file");
// 开始分片上传会话
InitiateMultipartUploadResponse initResponse = initiateMultipartUpload(bucketName, objectKey);
String uploadId = initResponse.uploadId();
// 计算文件大小和分片数量
long fileSize = fileToUpload.length();
int partSize = 5 * 1024 * 1024; // 假设每个分片大小为 5MB
int numberOfParts = (int) Math.ceil((double) fileSize / partSize);
// 上传每个分片
List<CompletedPart> completedParts = new ArrayList<>();
try (FileInputStream fis = new FileInputStream(fileToUpload)) {
for (int i = 1; i <= numberOfParts; i++) {
long startOffset = (i - 1) * partSize;
long currentPartSize = Math.min(partSize, fileSize - startOffset);
// 上传分片
UploadPartResponse partResponse = uploadPart(bucketName, objectKey, uploadId, i, fileToUpload, startOffset, currentPartSize);
if (partResponse != null) {
// 保存已完成分片的信息
CompletedPart completedPart = CompletedPart.builder()
.partNumber(i)
.eTag(partResponse.eTag())
.build();
completedParts.add(completedPart);
}
}
} catch (IOException e) {
e.printStackTrace();
}
// 完成分片上传
CompleteMultipartUploadResponse completeResponse = completeMultipartUpload(bucketName, objectKey, uploadId, completedParts);
if (completeResponse != null) {
System.out.println("分片上传成功!");
} else {
System.out.println("分片上传失败。");
}
}
}
public boolean downObject(String bucketName, String objectName, String targetPath) {
// 尝试下载对象到指定路径
try {
s3Client.getObject(GetObjectRequest.builder()
.bucket(bucketName)
.key(objectName)
.build(), new File(targetPath).toPath());
} catch (Exception e) {
// 如果出现异常则打印异常堆栈跟踪并返回 false
e.printStackTrace();
return false;
}
// 如果下载成功则返回 true
return true;
}
public InputStream getObject(String bucketName, String object) {
InputStream objectStream = null;
// 尝试获取指定存储桶和对象键的输入流
try {
objectStream = s3Client.getObject(GetObjectRequest.builder()
.bucket(bucketName)
.key(object)
.build());
} catch (Exception e) {
// 如果出现异常,则打印异常堆栈跟踪并返回 null
e.printStackTrace();
return null;
}
// 返回对象的输入流
return objectStream;
}
public ResponseBytes<GetObjectResponse> getObjectAsBytes(String bucketName, String object) {
ResponseBytes<GetObjectResponse> objectAsBytes = null;
// 尝试获取指定存储桶和对象键的内容作为字节
try {
objectAsBytes = s3Client.getObjectAsBytes(GetObjectRequest.builder()
.bucket(bucketName)
.key(object)
.build());
} catch (Exception e) {
// 如果出现异常,则打印异常堆栈跟踪并返回 null
e.printStackTrace();
return null;
}
// 返回对象的内容作为字节
return objectAsBytes;
}
public String presignedURLofObject(String bucketName, String object, int expire) {
URL url = null;
// 尝试生成预签名 URL
try {
url = s3Presigner.presignGetObject(GetObjectPresignRequest.builder()
.signatureDuration(Duration.ofMinutes(expire))
.getObjectRequest(GetObjectRequest.builder()
.bucket(bucketName)
.key(object)
.build())
.build()).url();
} catch (Exception e) {
// 如果出现异常则打印异常堆栈跟踪并返回 null
e.printStackTrace();
return null;
} finally {
// 关闭预签名客户端
s3Presigner.close();
}
// 返回预签名 URL 的字符串表示形式
return url.toString();
}
获取到的url是可以直接在浏览器预览的,但是要用其他插件(如 pdf.js)预览的话会出现跨域的错误,这个时候就需要给要访问的桶添加一下cors规则。
代码添加cors规则:
CORSRule corsRule = CORSRule.builder()
.allowedOrigins("http://ip:端口")//可以设置多个
//.allowedOrigins("*")
.allowedHeaders("Authorization")
.allowedMethods("GET","HEAD")
.exposeHeaders("Access-Control-Allow-Origin").build();
// 设置 CORS 配置
s3Client.putBucketCors(PutBucketCorsRequest.builder()
.bucket(bucketName)
.corsConfiguration(CORSConfiguration.builder()
.corsRules(corsRule)
.build())
.build());
S3控制台添加CORS规则:
点击你的桶选择权限,下拉找到这个设置,编辑添加下面的规则:
[
{
"AllowedHeaders": [
"Authorization"
],
"AllowedMethods": [
"GET",
"HEAD"
],
"AllowedOrigins": [
"http://ip:端口"
],
"ExposeHeaders": [
"Access-Control-Allow-Origin"
],
"MaxAgeSeconds": 3000
}
]
用S3 Browser添加
S3 Browser 是一款用于管理 Amazon S3 存储服务的第三方工具。它提供了一个图形用户界面(GUI),让用户能够更方便地上传、下载、管理和浏览存储在 Amazon S3 中的对象和存储桶。也可以用来连接minio或者其他存储。
添加你的配置等待扫描出桶名后,右击桶名选择CORS Configuration添加你的规则,点击apply使用。
<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
<CORSRule>
<AllowedOrigin>http://ip:端口</AllowedOrigin>
<AllowedMethod>GET</AllowedMethod>
<AllowedMethod>HEAD</AllowedMethod>
<MaxAgeSeconds>3000</MaxAgeSeconds>
<ExposeHeader>Access-Control-Allow-Origin</ExposeHeader>
<AllowedHeader>Authorization</AllowedHeader>
</CORSRule>
</CORSConfiguration>
因为是另一个项目的延伸版,所以有些方法反而改的更繁琐的一些。
import org.springframework.stereotype.Service;
import software.amazon.awssdk.core.ResponseBytes;
import software.amazon.awssdk.services.s3.model.Bucket;
import software.amazon.awssdk.services.s3.model.GetObjectResponse;
import software.amazon.awssdk.services.s3.model.HeadObjectResponse;
import software.amazon.awssdk.services.s3.model.S3Object;
import java.io.InputStream;
import java.util.List;
import java.util.Map;
/**
* 定义与 AWS S3 客户端交互的一般功能。
*/
@Service
public interface S3Service {
/**
* 判断指定的存储桶是否存在。
*
* @param bucketName 存储桶名称。
* @return 如果存储桶存在返回 true,否则返回 false。
*/
boolean ifExistsBucket(String bucketName);
/**
* 创建一个新的存储桶。如果存储桶已存在,则抛出运行时异常。
*
* @param bucketName 新建的存储桶名称。
* @return 如果存储桶创建成功返回 true。
* @throws RuntimeException 如果存储桶已存在。
*/
boolean createBucket(String bucketName) throws RuntimeException;
/**
* 删除一个存储桶。存储桶必须为空;否则不会被删除。
* 即使指定的存储桶不存在也会返回 true。
*
* @param bucketName 要删除的存储桶名称。
* @return 如果存储桶被删除或不存在返回 true。
*/
boolean removeBucket(String bucketName);
/**
* 列出当前 S3 服务器上所有存在的存储桶。
*
* @return 存储桶列表。
*/
List<Bucket> alreadyExistBuckets();
/**
* 列出存储桶中的对象,可选地通过前缀过滤并指定是否包括子目录。
*
* @param bucketName 存储桶名称。
* @param predir 前缀过滤条件。
* @param recursive 是否包括子目录。
* @return S3 对象列表。
*/
List<S3Object> listObjects(String bucketName, String predir, boolean recursive);
/**
* 列出存储桶中的对象,通过前缀过滤。
*
* @param bucketName 存储桶名称。
* @param predir 前缀过滤条件。
* @return S3 对象列表。
*/
List<S3Object> listObjects(String bucketName, String predir);
/**
* 复制一个对象文件从一个存储桶到另一个存储桶。
*
* @param pastBucket 源文件所在的存储桶。
* @param pastObject 源文件在存储桶内的路径。
* @param newBucket 将要复制进的目标存储桶。
* @param newObject 将要复制进的目标存储桶内的路径。
* @return 如果复制成功返回 true。
*/
boolean copyObject(String pastBucket, String pastObject, String newBucket, String newObject);
/**
* 下载一个对象。
*
* @param bucketName 存储桶名称。
* @param objectName 对象路径及名称(例如:2022/02/02/xxx.doc)。
* @param targetPath 目标路径及名称(例如:/opt/xxx.doc)。
* @return 如果下载成功返回 true。
*/
boolean downObject(String bucketName, String objectName, String targetPath);
/**
* 返回对象的签名 URL。
*
* @param bucketName 存储桶名称。
* @param object 对象路径及名称。
* @param expire 过期时间(分钟)。
* @return 签名 URL。
*/
String presignedURLofObject(String bucketName, String object, int expire);
/**
* 返回带有额外参数的对象签名 URL。
*
* @param bucketName 存储桶名称。
* @param object 对象路径及名称。
* @param expire 过期时间(分钟)。
* @param map 额外参数。
* @return 签名 URL。
*/
String presignedURLofObject(String bucketName, String object, int expire, Map<String, String> map);
/**
* 删除一个对象。
*
* @param bucketName 存储桶名称。
* @param object 对象名称(路径)。
* @return 如果删除成功返回 true。
*/
boolean deleteObject(String bucketName, String object);
/**
* 上传一个对象,使用本地文件作为源。
*
* @param bucketName 存储桶名称。
* @param targetObject 目标对象的名称。
* @param sourcePath 本地文件路径(例如:/opt/1234.doc)。
* @return 如果上传成功返回 true。
*/
boolean uploadObject(String bucketName, String targetObject, String sourcePath);
/**
* 上传一个对象,使用输入流作为源。
*
* @param bucketName 存储桶名称。
* @param object 对象名称。
* @param inputStream 输入流。
* @param size 对象大小。
* @return 如果上传成功返回 true。
*/
boolean putObject(String bucketName, String object, InputStream inputStream, long size);
/**
* 上传一个带有标签的对象。
*
* @param bucketName 存储桶名称。
* @param object 对象名称。
* @param inputStream 输入流。
* @param size 对象大小。
* @param tags 标签集合。
* @return 如果上传成功返回 true。
*/
boolean putObject(String bucketName, String object, InputStream inputStream, long size, Map<String, String> tags);
/**
* 获取一个对象。
*
* @param bucketName 存储桶名称。
* @param object 对象名称。
* @return GetObjectResponse 类型的输入流。
*/
InputStream getObject(String bucketName, String object);
/**
* 获取一个对象的内容作为字节流。
*
* @param bucketName 存储桶名称。
* @param object 对象名称。
* @return 包含对象内容的字节流。
*/
ResponseBytes<GetObjectResponse> getObjectAsBytes(String bucketName, String object);
/**
* 判断一个文件是否存在于存储桶中。
*
* @param bucketName 存储桶名称。
* @param filename 文件名称。
* @param recursive 是否递归搜索。
* @return 如果文件存在返回 true。
*/
boolean fileifexist(String bucketName, String filename, boolean recursive);
/**
* 获取一个对象的标签。
*
* @param bucketName 存储桶名称。
* @param object 对象名称。
* @return 标签集合。
*/
Map<String, String> getTags(String bucketName, String object);
/**
* 为存储桶内的对象添加标签。
*
* @param bucketName 存储桶名称。
* @param object 对象名称。
* @param addTags 要添加的标签。
* @return 如果添加成功返回 true。
*/
boolean addTags(String bucketName, String object, Map<String, String> addTags);
/**
* 获取对象的对象信息和元数据。
*
* @param bucketName 存储桶名称。
* @param object 对象名称。
* @return HeadObjectResponse 类型的对象信息和元数据。
*/
HeadObjectResponse statObject(String bucketName, String object);
/**
* 判断一个对象是否存在。
*
* @param bucketName 存储桶名称。
* @param objectName 对象名称。
* @return 如果对象存在返回 true。
*/
boolean ifExistObject(String bucketName, String objectName);
/**
* 从其他对象名称中获取元数据名称。
*
* @param objectName 对象名称。
* @return 元数据名称。
*/
String getMetaNameFromOther(String objectName);
/**
* 更改对象的标签。
*
* @param object 对象名称。
* @param tag 新的标签。
* @return 如果更改成功返回 true。
*/
boolean changeTag(String object, String tag);
/**
* 设置存储桶为公共访问。
*
* @param bucketName 存储桶名称。
*/
void BucketAccessPublic(String bucketName);
}
import com.xagxsj.erms.model.BucketName;
import com.xagxsj.erms.model.ObjectTags;
import com.xagxsj.erms.service.S3Service;
import com.xagxsj.erms.utils.FileUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import software.amazon.awssdk.core.ResponseBytes;
import software.amazon.awssdk.core.sync.RequestBody;
import software.amazon.awssdk.services.s3.S3Client;
import software.amazon.awssdk.services.s3.model.*;
import software.amazon.awssdk.services.s3.presigner.S3Presigner;
import software.amazon.awssdk.services.s3.presigner.model.GetObjectPresignRequest;
import java.io.File;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.net.URLEncoder;
import java.time.Duration;
import java.util.*;
import java.util.logging.Logger;
import java.util.stream.Collectors;
@Service
public class S3ServiceImpl implements S3Service {
private final Logger log = Logger.getLogger(this.getClass().getName());
@Qualifier("s3Client")
@Autowired
S3Client s3Client;
@Qualifier("s3Presigner")
@Autowired
S3Presigner s3Presigner;
@Override
public boolean ifExistsBucket(String bucketName) {
// 尝试发送 HEAD 请求来检查存储桶是否存在
try {
HeadBucketResponse headBucketResponse = s3Client.headBucket(HeadBucketRequest.builder().bucket(bucketName).build());
} catch (S3Exception e) {
// 如果捕获到 S3 异常且状态码为 404,则说明存储桶不存在
if (e.statusCode() == 404) {
return false;
} else {
// 打印异常堆栈跟踪
e.printStackTrace();
}
}
// 如果没有抛出异常或状态码不是 404,则说明存储桶存在
return true;
}
@Override
public boolean createBucket(String bucketName) throws RuntimeException {
// 检查存储桶是否已经存在
if (ifExistsBucket(bucketName)) {
// 如果存储桶已存在,则抛出运行时异常
throw new RuntimeException("桶已存在");
}
// 创建新的存储桶
S3Response bucket = s3Client.createBucket(CreateBucketRequest.builder().bucket(bucketName).build());
// 检查存储桶是否创建成功
return ifExistsBucket(bucketName);
}
@Override
public boolean removeBucket(String bucketName) {
// 如果存储桶不存在,则直接返回 true
if (!ifExistsBucket(bucketName)) {
return true;
}
// 删除存储桶
s3Client.deleteBucket(DeleteBucketRequest.builder().bucket(bucketName).build());
// 检查存储桶是否已被删除
return !ifExistsBucket(bucketName);
}
@Override
public List<Bucket> alreadyExistBuckets() {
// 列出所有存在的存储桶
List<Bucket> buckets = s3Client.listBuckets().buckets();
return buckets;
}
@Override
public boolean fileifexist(String bucketName, String filename, boolean recursive) {
// 初始化一个布尔值用于标记文件是否存在
boolean flag = false;
// 构建第一次的 ListObjectsV2 请求
ListObjectsV2Request request = ListObjectsV2Request.builder().bucket(bucketName).build();
ListObjectsV2Response response;
// 循环处理直到所有分页的数据都被检索
do {
// 发送请求并获取响应
response = s3Client.listObjectsV2(request);
// 遍历响应中的内容
for (S3Object content : response.contents()) {
// 如果找到匹配的文件名,则设置标志位为真
if (content.key().equals(filename)) {
flag = true;
break;
}
}
// 构建下一次请求,如果响应被截断,则继续获取下一页的数据
request = ListObjectsV2Request.builder()
.bucket(bucketName)
.continuationToken(response.nextContinuationToken())
.build();
} while (response.isTruncated());
// 返回文件是否存在
return flag;
}
@Override
public List<S3Object> listObjects(String bucketName, String predir, boolean recursive) {
// 构建 ListObjects 请求以列出具有指定前缀的文件
List<S3Object> contents = s3Client.listObjects(ListObjectsRequest.builder()
.bucket(bucketName)
.prefix(predir)
.maxKeys(1000)
.build()).contents();
return contents;
}
@Override
public List<S3Object> listObjects(String bucketName, String predir) {
// 构建 ListObjects 请求以列出具有指定前缀的文件
List<S3Object> contents = s3Client.listObjects(ListObjectsRequest.builder()
.bucket(bucketName)
.prefix(predir)
.maxKeys(1000)
.build()).contents();
return contents;
}
@Override
public boolean copyObject(String pastBucket, String pastObject, String newBucket, String newObject) {
// 尝试复制对象
try {
CopyObjectResponse copyObjectResponse = s3Client.copyObject(CopyObjectRequest.builder()
.sourceBucket(pastBucket)
.sourceKey(pastObject)
.destinationBucket(newBucket)
.destinationKey(newObject)
.build());
} catch (Exception e) {
// 如果出现异常则打印异常堆栈跟踪并返回 false
e.printStackTrace();
return false;
}
// 如果复制成功则返回 true
return true;
}
@Override
public boolean downObject(String bucketName, String objectName, String targetPath) {
// 尝试下载对象到指定路径
try {
s3Client.getObject(GetObjectRequest.builder()
.bucket(bucketName)
.key(objectName)
.build(), new File(targetPath).toPath());
} catch (Exception e) {
// 如果出现异常则打印异常堆栈跟踪并返回 false
e.printStackTrace();
return false;
}
// 如果下载成功则返回 true
return true;
}
@Override
public String presignedURLofObject(String bucketName, String object, int expire) {
URL url = null;
// 尝试生成预签名 URL
try {
url = s3Presigner.presignGetObject(GetObjectPresignRequest.builder()
.signatureDuration(Duration.ofMinutes(expire))
.getObjectRequest(GetObjectRequest.builder()
.bucket(bucketName)
.key(object)
.build())
.build()).url();
} catch (Exception e) {
// 如果出现异常则打印异常堆栈跟踪并返回 null
e.printStackTrace();
return null;
} finally {
// 关闭预签名客户端
s3Presigner.close();
}
// 返回预签名 URL 的字符串表示形式
return url.toString();
}
@Override
public String presignedURLofObject(String bucketName, String object, int expire, Map<String, String> map) {
URL url = null;
// 尝试生成预签名 URL
try {
url = s3Presigner.presignGetObject(GetObjectPresignRequest.builder()
.signatureDuration(Duration.ofMinutes(expire))
.getObjectRequest(GetObjectRequest.builder()
.bucket(bucketName)
.key(object)
.build())
.build()).url();
} catch (Exception e) {
// 如果出现异常则打印异常堆栈跟踪并返回 null
e.printStackTrace();
return null;
} finally {
// 关闭预签名客户端
s3Presigner.close();
}
// 返回预签名 URL 的字符串表示形式
return url.toString();
}
@Override
public boolean deleteObject(String bucketName, String object) {
// 尝试删除对象
try {
s3Client.deleteObject(DeleteObjectRequest.builder()
.bucket(bucketName)
.key(object)
.build());
} catch (Exception e) {
// 如果出现异常则打印异常堆栈跟踪并返回 false
e.printStackTrace();
return false;
}
// 如果删除成功则返回 true
return true;
}
@Override
public boolean uploadObject(String bucketName, String targetObject, String sourcePath) {
// 尝试上传本地文件到指定的存储桶和对象键
try {
s3Client.putObject(PutObjectRequest.builder()
.bucket(bucketName)
.key(targetObject)
.build(), RequestBody.fromFile(new File(sourcePath)));
} catch (Exception e) {
// 如果出现异常,则打印异常堆栈跟踪并返回 false
e.printStackTrace();
return false;
}
// 如果上传成功则返回 true
return true;
}
@Override
public boolean putObject(String bucketName, String object, InputStream inputStream, long size) {
// 尝试从输入流上传数据到指定的存储桶和对象键
try {
s3Client.putObject(PutObjectRequest.builder()
.bucket(bucketName)
.key(object)
.build(), RequestBody.fromInputStream(inputStream, size));
} catch (Exception e) {
// 如果出现异常,则打印异常堆栈跟踪并返回 false
e.printStackTrace();
return false;
}
// 如果上传成功则返回 true
return true;
}
@Override
public boolean putObject(String bucketName, String object, InputStream inputStream, long size, Map<String, String> tags) {
// 尝试从输入流上传数据到指定的存储桶和对象键,并设置标签
try {
// 将标签映射转换为标签集合
Collection<Tag> tagList = tags.entrySet().stream().map(entry ->
Tag.builder().key(entry.getKey()).value(entry.getValue()).build())
.collect(Collectors.toList());
// 上传对象并设置标签
s3Client.putObject(PutObjectRequest.builder()
.bucket(bucketName)
.key(object)
.tagging(Tagging.builder()
.tagSet(tagList)
.build())
.build(), RequestBody.fromInputStream(inputStream, size));
} catch (Exception e) {
// 如果出现异常,则打印异常堆栈跟踪并返回 false
e.printStackTrace();
return false;
}
// 如果上传成功则返回 true
return true;
}
@Override
public InputStream getObject(String bucketName, String object) {
InputStream objectStream = null;
// 尝试获取指定存储桶和对象键的输入流
try {
objectStream = s3Client.getObject(GetObjectRequest.builder()
.bucket(bucketName)
.key(object)
.build());
} catch (Exception e) {
// 如果出现异常,则打印异常堆栈跟踪并返回 null
e.printStackTrace();
return null;
}
// 返回对象的输入流
return objectStream;
}
@Override
public ResponseBytes<GetObjectResponse> getObjectAsBytes(String bucketName, String object) {
ResponseBytes<GetObjectResponse> objectAsBytes = null;
// 尝试获取指定存储桶和对象键的内容作为字节
try {
objectAsBytes = s3Client.getObjectAsBytes(GetObjectRequest.builder()
.bucket(bucketName)
.key(object)
.build());
} catch (Exception e) {
// 如果出现异常,则打印异常堆栈跟踪并返回 null
e.printStackTrace();
return null;
}
// 返回对象的内容作为字节
return objectAsBytes;
}
@Override
public Map<String, String> getTags(String bucketName, String object) {
Map<String, String> tags = null;
// 尝试获取指定存储桶和对象键的标签
try {
List<Tag> tagList = s3Client.getObjectTagging(GetObjectTaggingRequest.builder()
.bucket(bucketName)
.key(object)
.build()).tagSet();
// 将标签集合转换为标签映射
tags = tagList.stream().collect(Collectors.toMap(Tag::key, Tag::value));
} catch (Exception e) {
// 如果出现异常,则打印异常堆栈跟踪并返回 null
e.printStackTrace();
return null;
}
// 返回标签映射
return tags;
}
@Override
public boolean addTags(String bucketName, String object, Map<String, String> addTags) {
Map<String, String> oldTags = new HashMap<>();
Map<String, String> newTags = new HashMap<>();
// 获取现有标签
try {
oldTags = getTags(bucketName, object);
if (oldTags.size() > 0) {
newTags.putAll(oldTags);
}
} catch (Exception e) {
// 如果出现异常,则打印异常堆栈跟踪并提示没有旧标签
e.printStackTrace();
System.out.println("原存储桶无老旧标签");
}
// 添加新标签
if (addTags != null && addTags.size() > 0) {
newTags.putAll(addTags);
}
// 将新标签集合转换为标签列表
Collection<Tag> tagList = newTags.entrySet().stream().map(entry ->
Tag.builder().key(entry.getKey()).value(entry.getValue()).build())
.collect(Collectors.toList());
// 设置新标签
try {
s3Client.putObjectTagging(PutObjectTaggingRequest.builder()
.bucket(bucketName)
.key(object)
.tagging(Tagging.builder()
.tagSet(tagList).build())
.build());
} catch (Exception e) {
// 如果出现异常,则打印异常堆栈跟踪并返回 false
e.printStackTrace();
return false;
}
// 如果设置成功则返回 true
return true;
}
@Override
public HeadObjectResponse statObject(String bucketName, String object) {
HeadObjectResponse headObjectResponse = null;
// 尝试获取指定存储桶和对象键的元数据
try {
headObjectResponse = s3Client.headObject(HeadObjectRequest.builder()
.bucket(bucketName)
.key(object)
.build());
} catch (Exception e) {
// 如果出现异常,则打印异常堆栈跟踪并返回 null
e.printStackTrace();
return null;
}
// 返回对象的元数据
return headObjectResponse;
}
@Override
public boolean ifExistObject(String bucketName, String objectName) {
// 检查指定存储桶和对象键的对象是否存在
return listObjects(bucketName, objectName, true).size() >= 1;
}
@Override
public String getMetaNameFromOther(String objectName) {
String metaObject = "";
// 获取元数据存储桶中特定前缀的对象列表
List<S3Object> s3Objects = listObjects(BucketName.METADATA, FileUtil.getPreMeta(objectName), true);
if (s3Objects.size() == 1) {
try {
// 获取第一个对象的键并获取其标签
metaObject = s3Objects.get(0).key();
Map<String, String> tags = getTags(BucketName.METADATA, metaObject);
// 编码文件名标签
String fileName = tags.get(ObjectTags.FILENAME);
return URLEncoder.encode(fileName, "UTF-8");
} catch (UnsupportedEncodingException e) {
// 如果出现异常,则打印异常堆栈跟踪
e.printStackTrace();
}
}
// 如果未找到对象或编码失败,则返回原始文件名
return FileUtil.getFileName(metaObject);
}
@Override
public boolean changeTag(String object, String tag) {
// 尝试更改指定对象的标签
try {
s3Client.putObjectTagging(PutObjectTaggingRequest.builder()
.bucket(BucketName.METADATA)
.key(object)
.tagging(Tagging.builder()
.tagSet(Tag.builder()
.key(ObjectTags.FILENAME)
.value(tag)
.build())
.build())
.build());
} catch (Exception e) {
// 如果出现异常,则打印异常堆栈跟踪并返回 false
e.printStackTrace();
return false;
}
// 如果更改成功则返回 true
return true;
}
@Override
public void BucketAccessPublic(String bucketName) {
// 设置存储桶策略为公共访问
String config = "{\"Version\":\"2012-10-17\",\"Statement\":[{\"Effect\":\"Allow\",\"Principal\":{\"AWS\":[\"*\"]},\"Action\":[\"s3:ListBucketMultipartUploads\",\"s3:GetBucketLocation\",\"s3:ListBucket\"],\"Resource\":[\"arn:aws:s3:::" + bucketName + "\"]},{\"Effect\":\"Allow\",\"Principal\":{\"AWS\":[\"*\"]},\"Action\":[\"s3:ListMultipartUploadParts\",\"s3:PutObject\",\"s3:AbortMultipartUpload\",\"s3:DeleteObject\",\"s3:GetObject\"],\"Resource\":[\"arn:aws:s3:::" + bucketName + "/*\"]}]}";
try {
// 应用存储桶策略
s3Client.putBucketPolicy(PutBucketPolicyRequest.builder()
.bucket(bucketName)
.policy(config).build());
} catch (Exception e) {
// 如果出现异常,则打印异常堆栈跟踪
e.printStackTrace();
}
}
}