使用支持S3协议的云存储作为文件服务器。
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

272 lines
9.0 KiB

package com.fanruan.fs.s3.repository.core;
import com.amazonaws.auth.AWSStaticCredentialsProvider;
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.client.builder.AwsClientBuilder;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
import com.amazonaws.services.s3.model.CopyObjectRequest;
import com.amazonaws.services.s3.model.DeleteObjectRequest;
import com.amazonaws.services.s3.model.GetObjectRequest;
import com.amazonaws.services.s3.model.ListObjectsRequest;
import com.amazonaws.services.s3.model.ObjectListing;
import com.amazonaws.services.s3.model.ObjectMetadata;
import com.amazonaws.services.s3.model.PutObjectRequest;
import com.amazonaws.services.s3.model.S3Object;
import com.amazonaws.services.s3.model.S3ObjectSummary;
import com.fanruan.api.log.LogKit;
import com.fanruan.api.util.StringKit;
import com.fr.io.repository.FineFileEntry;
import com.fr.io.repository.base.BaseResourceRepository;
import com.fr.stable.Filter;
import com.fr.workspace.resource.ResourceIOException;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.List;
/**
* @author richie
* @version 10.0
* Created by richie on 2020/6/15
*/
public class S3ResourceRepository extends BaseResourceRepository {
private static final String DELIMITER = "/";
private final AmazonS3 s3;
private final String bucket;
public S3ResourceRepository(String repoName, String workRoot, S3Config config) {
super(repoName, workRoot);
BasicAWSCredentials credentials = new BasicAWSCredentials(config.getAccessKeyId(), config.getAccessKeySecret());
this.s3 = AmazonS3ClientBuilder.standard()
.withEndpointConfiguration(new AwsClientBuilder.EndpointConfiguration(config.getEndPoint(), config.getRegion()))
.withCredentials(new AWSStaticCredentialsProvider(credentials)).build();
this.bucket = config.getBucket();
}
@Override
public String getSeparator() {
return "/";
}
@Override
public FineFileEntry getEntry(String path) {
GetObjectRequest request = new GetObjectRequest(bucket, path);
S3Object s3Object = s3.getObject(request);
return s3Object2FileEntry(s3Object, path);
}
@Override
public FineFileEntry[] listEntry(String dir) {
List<FineFileEntry> result = new ArrayList<>();
if (!dir.endsWith(DELIMITER)) {
dir += DELIMITER;
}
ListObjectsRequest listObjectsRequest = new ListObjectsRequest().withBucketName(bucket)
.withPrefix(dir).withDelimiter(DELIMITER);
ObjectListing objectListing = s3.listObjects(listObjectsRequest);
for (S3ObjectSummary summary : objectListing.getObjectSummaries()) {
String key = summary.getKey();
if (!key.endsWith(DELIMITER)) {
result.add(s3Object2FileEntry(summary, key));
}
}
for (String prefix : objectListing.getCommonPrefixes()) {
FineFileEntry entry = new FineFileEntry(prefix);
entry.setDirectory(true);
result.add(entry);
}
return result.toArray(new FineFileEntry[0]);
}
private FineFileEntry s3Object2FileEntry(S3ObjectSummary s3Object, String path) {
FineFileEntry entry = new FineFileEntry(path);
entry.setDirectory(s3Object.getKey().endsWith("/"));
entry.setSize(s3Object.getSize());
entry.setTimestamp(s3Object.getLastModified().getTime());
return entry;
}
private FineFileEntry s3Object2FileEntry(S3Object s3Object, String path) {
FineFileEntry entry = new FineFileEntry(path);
entry.setDirectory(s3Object.getKey().endsWith("/"));
entry.setSize(s3Object.getObjectMetadata().getContentLength());
entry.setTimestamp(s3Object.getObjectMetadata().getLastModified().getTime());
return entry;
}
@Override
public URL getResource(String path) {
throw new RuntimeException("Not support method.");
}
@Override
public InputStream read(String filePath) throws ResourceIOException {
GetObjectRequest request = new GetObjectRequest(bucket, filePath);
try {
return s3.getObject(request).getObjectContent();
} catch (Exception e) {
return new ByteArrayInputStream(new byte[0]);
}
}
@Override
public void write(String path, byte[] data) {
ObjectMetadata metadata;
try {
metadata = s3.getObjectMetadata(bucket, path);
} catch (Exception e) {
metadata = new ObjectMetadata();
String mimeType = URLConnection.guessContentTypeFromName(path);
if (mimeType != null) {
metadata.setContentType(mimeType);
}
metadata.setContentLength(data.length);
}
s3.putObject(bucket, path, new ByteArrayInputStream(data), metadata);
}
@Override
public boolean createFile(String path) {
PutObjectRequest request = new PutObjectRequest(bucket, path, new ByteArrayInputStream(new byte[0]), new ObjectMetadata());
try {
s3.putObject(request);
} catch (Exception e) {
return false;
}
return true;
}
@Override
public boolean createDirectory(String path) {
PutObjectRequest request = new PutObjectRequest(bucket, path + "/", new ByteArrayInputStream(new byte[0]), new ObjectMetadata());
try {
s3.putObject(request);
} catch (Exception e) {
return false;
}
return true;
}
@Override
public boolean delete(String path) {
try {
s3.deleteObject(bucket, path);
} catch (Exception e) {
LogKit.error(e.getMessage(), e);
return false;
}
return true;
}
@Override
public boolean exist(String path) {
try {
return !s3.listObjects(bucket, path).getObjectSummaries().isEmpty();
} catch (Exception e) {
return false;
}
}
@Override
public String[] list(String dir, final Filter<String> filter) {
List<String> result = new ArrayList<>();
if (!dir.endsWith(DELIMITER)) {
dir += DELIMITER;
}
ListObjectsRequest listObjectsRequest = new ListObjectsRequest().withBucketName(bucket)
.withPrefix(dir).withDelimiter(DELIMITER);
ObjectListing objectListing = s3.listObjects(listObjectsRequest);
for (S3ObjectSummary objectSummary : objectListing.getObjectSummaries()) {
String[] arr = objectSummary.getKey().split(DELIMITER);
String name = arr[arr.length - 1];
if (filter == null) {
result.add(name);
} else {
if (filter.accept(name)) {
result.add(name);
}
}
}
for (String prefix : objectListing.getCommonPrefixes()) {
String[] arr = prefix.split(DELIMITER);
String name = arr[arr.length - 1] + DELIMITER;
if (filter == null) {
result.add(name);
} else {
if (filter.accept(name)) {
result.add(name);
}
}
}
return result.toArray(new String[0]);
}
@Override
public boolean isDirectory(String path) {
if (path.endsWith(DELIMITER)) {
return true;
}
ObjectListing listing = s3.listObjects(bucket, path);
if (listing.getObjectSummaries().isEmpty()) {
return false;
}
if (listing.getObjectSummaries().size() > 1) {
return true;
} else {
S3ObjectSummary summary = listing.getObjectSummaries().get(0);
return !StringKit.equals(listing.getPrefix(), summary.getKey());
}
}
@Override
public long lastModified(String path) {
S3Object s3Object = s3.getObject(bucket, path);
if (s3Object == null) {
return -1L;
}
return s3Object.getObjectMetadata().getLastModified().getTime();
}
@Override
public long length(String path) {
S3Object s3Object = s3.getObject(bucket, path);
if (s3Object == null) {
return -1L;
}
return s3Object.getObjectMetadata().getContentLength();
}
@Override
public boolean rename(String path, String newPath) throws ResourceIOException {
try {
CopyObjectRequest copyObjRequest = new CopyObjectRequest(bucket,
path, bucket, newPath);
s3.copyObject(copyObjRequest);
s3.deleteObject(new DeleteObjectRequest(bucket, path));
} catch (Exception e) {
LogKit.error(e.getMessage(), e);
return false;
}
return true;
}
@Override
public void shutDown() {
s3.shutdown();
}
@Override
public String getIdentity() {
return S3RepositoryFactory.IDENTITY;
}
}