非线程安全版
import com.amazonaws.annotation.NotThreadSafe;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.model.*;
import java.util.*;
@NotThreadSafe
public class S3ObjectsScanner implements Iterable<String> {
private final static int DEFAULT_MAX_KEYS = 1000;
/**
* S3客户端对象
*/
private AmazonS3 client;
/**
* 桶名
*/
private String bucketName;
/**
* 起始索引
*/
private String startPrefix;
/**
* 终止索引
*/
private String endPrefix;
/**
* key的最大缓存个数
*/
private int maxKeys;
public S3ObjectsScanner() {
this.maxKeys = DEFAULT_MAX_KEYS;
}
public S3ObjectsScanner(AmazonS3 client, String bucketName) {
this();
this.client = client;
this.bucketName = bucketName;
}
@NotThreadSafe
private class Itr implements Iterator<String> {
private final ListObjectsV2Request request;
private final Queue<String> queue;
private final String endPrefix;
private boolean lastPage = false;
Itr() {
this.endPrefix = S3ObjectsScanner.this.endPrefix;
request = new ListObjectsV2Request()
.withBucketName(bucketName)
.withStartAfter(startPrefix)
.withMaxKeys(maxKeys);
queue = new ArrayDeque<>(maxKeys);
}
@Override
public synchronized boolean hasNext() {
if (queue.isEmpty() && !lastPage) {
loadMore();
}
return !queue.isEmpty();
}
@Override
public synchronized String next() {
if (!hasNext()) {
throw new NoSuchElementException();
}
return queue.poll();
}
private void loadMore() {
// 发送请求
ListObjectsV2Result result = client.listObjectsV2(request);
// 准备下一次请求
prepareNextReq(result);
// 提取Keys
extraKeys(result.getObjectSummaries());
}
private void prepareNextReq(ListObjectsV2Result result) {
// 检查是否还有剩余数据
if (result.isTruncated()) {
request.setContinuationToken(result.getNextContinuationToken());
} else {
// 没有剩余数据,置位
lastPage = true;
}
}
private void extraKeys(List<S3ObjectSummary> summaries) {
for (S3ObjectSummary summary : summaries) {
String key = summary.getKey();
// 检查是否到达结束的位置
if (isOver(key)) {
// 结束,标志位置位,结束循环
lastPage = true;
return;
}
// 未结束,入队
queue.offer(key);
}
}
private boolean isOver(String key) {
// 如果没有指定“终止前缀”,无论什么key都不算结束
if (endPrefix == null) {
return false;
}
// 如果key小于“终止前缀”,也不算结束
if (endPrefix.compareTo(key) > 0) {
return false;
}
return true;
}
}
@Override
public Iterator<String> iterator() {
return new Itr();
}
public AmazonS3 getClient() {
return client;
}
public S3ObjectsScanner withClient(AmazonS3 client) {
this.client = client;
return this;
}
public String getBucketName() {
return bucketName;
}
public S3ObjectsScanner withBucketName(String bucketName) {
this.bucketName = bucketName;
return this;
}
public String getStartPrefix() {
return startPrefix;
}
public S3ObjectsScanner withStartPrefix(String startPrefix) {
this.startPrefix = startPrefix;
return this;
}
public String getEndPrefix() {
return endPrefix;
}
public S3ObjectsScanner withEndPrefix(String endPrefix) {
this.endPrefix = endPrefix;
return this;
}
public int getMaxKeys() {
return maxKeys;
}
public S3ObjectsScanner withMaxKeys(int maxKeys) {
this.maxKeys = maxKeys;
return this;
}
}