一、Amazon S3介绍:
官方介绍:amazon (S3) 是一个公开的服务,Web 应用程序开发人员可以使用它存储数字资产,包括图片、视频、音乐和文档。 S3 提供一个 RESTful API 以编程方式实现与该服务的交互。
通俗理解:以桶作为容器。以桶内全路径作为key,以文件作为value的文件存储方式

二、springboot集成Amazon s3
在项目的pom文件中增加如下依赖
<!--aws s3-->
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-java-sdk-s3</artifactId>
<version>1.11.336</version>
</dependency>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-java-sdk-core</artifactId>
<version>1.11.336</version>
</dependency>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-java-sdk-kms</artifactId>
<version>1.11.336</version>
</dependency>
三、Amazon S3工具类
实现功能:
方法 方法名创建s3的客户端连接public AmazonS3 createS3Client(String accessKeyId,String secretAccessKey,String endPoint)上传文件public boolean uploadFile(File file, String fileKey)上传文件流 public boolean uploadFileByStream(InputStream inputStream, String fileKey)从s3下载文件public InputStream downloadFile(String fileKey)
同一个桶内移动文件public boolean mvFile(String oldFileKey,String newFileKey)
删除单个文件public boolean deleteFile(String fileKey)
删除多个文件public boolean deleteFiles(String[] fileList)
查看文件是否存在public boolean exist(String fileKey)
根据prefix获取文件列表public List<S3ObjectSummary> searchPathFileByPrefix(String prefix)
生成文件的预签名urlpublic String generalUrl(String fileKey)
根据预签名url下载文件public File downloadFromUrl(String url,String filePath)
package com.testcase.s3;
import com.amazonaws.ClientConfiguration;
import com.amazonaws.HttpMethod;
import com.amazonaws.auth.AWSCredentials;
import com.amazonaws.auth.AWSStaticCredentialsProvider;
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.client.builder.AwsClientBuilder;
import com.amazonaws.regions.Regions;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
import com.amazonaws.services.s3.model.*;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.HttpClients;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
/**
* Created with IntelliJ IDEA.
* Description:Amazon s3工具类
* User: rice
*/
@Log4j2
public class S3ToolUtils {
//S3访问密钥
private String accessKeyId;
//S3加密访问密钥
private String secretAccessKey;
//服务端点
private String endPoint;
//桶名
private String bucketName;
public S3ToolUtils(String accessKeyId, String secretAccessKey, String endPoint) {
this.accessKeyId = accessKeyId;
this.secretAccessKey = secretAccessKey;
this.endPoint = endPoint;
this.bucketName = bucketName;
}
/**
* 创建一个对象存储桶客户端连接
* @param accessKeyId:AWS访问密钥
* @param secretAccessKey:AWS加密访问密钥
* @param endPoint:服务端点
* @return AmazonS3
*/
public AmazonS3 createS3Client(String accessKeyId,String secretAccessKey,String endPoint){
//创建s3 client
ClientConfiguration clientConfiguration = new ClientConfiguration();
//添加客户端最大连接数
clientConfiguration.setMaxConnections(1000);
AWSCredentials awsCredentials = new BasicAWSCredentials(accessKeyId, secretAccessKey);
AmazonS3 client = AmazonS3ClientBuilder.standard()
.withCredentials(new AWSStaticCredentialsProvider(awsCredentials))
.withEndpointConfiguration(new AwsClientBuilder.EndpointConfiguration(endPoint, Regions.CN_NORTH_1.getName()))
.withClientConfiguration(clientConfiguration)
.withPathStyleAccessEnabled(true).build();
return client;
}
/**
* 上传文件到对象存储桶
* @param file
* @param fileKey
* @return Boolean
*/
public boolean uploadFile(File file, String fileKey){
try{
//获取客户端连接
AmazonS3 s3Client = this.createS3Client(accessKeyId,secretAccessKey,endPoint);
//上传文件
s3Client.putObject(bucketName,fileKey,file);
}catch (Exception e){
log.error(e);
return false;
}
return true;
}
/**
* 上传文件到对象存储桶-文件流方式
* @param inputStream
* @param fileKey
* @return boolean
*/
public boolean uploadFileByStream(InputStream inputStream, String fileKey){
try{
//获取客户端连接
AmazonS3 s3Client = this.createS3Client(accessKeyId,secretAccessKey,endPoint);
//上传文件
s3Client.putObject(bucketName,fileKey,inputStream,new ObjectMetadata());
}catch (Exception e){
log.error(e);
return false;
}
return true;
}
/**
* 下载文件
* @param fileKey
* @return
*/
public InputStream downloadFile(String fileKey){
try{
//获取客户端连接
AmazonS3 s3Client = this.createS3Client(accessKeyId,secretAccessKey,endPoint);
//上传文件
S3Object object = s3Client.getObject(bucketName, fileKey);
return object.getObjectContent();
}catch (Exception e){
log.error(e);
return null;
}
}
/**
* 移动文件(删除原文件)
* @param oldFileKey 原全路径
* @param newFileKey 新全路径
* @return boolean
*/
public boolean mvFile(String oldFileKey,String newFileKey){
try{
//获取客户端连接
AmazonS3 s3Client = this.createS3Client(accessKeyId,secretAccessKey,endPoint);
//复制文件
CopyObjectRequest copyObjectRequest = new CopyObjectRequest(bucketName, oldFileKey, bucketName, newFileKey);
s3Client.copyObject(copyObjectRequest);
//删除原文件
s3Client.deleteObject(new DeleteObjectRequest(bucketName,oldFileKey));
}catch (Exception e){
log.error(e);
return false;
}
return true;
}
/**
* 删除文件
* @param fileKey 删除文件全路径
* @return boolean
*/
public boolean deleteFile(String fileKey){
try{
//获取客户端连接
AmazonS3 s3Client = this.createS3Client(accessKeyId,secretAccessKey,endPoint);
//删除文件
s3Client.deleteObject(bucketName,fileKey);
}catch (Exception e){
log.error(e);
return false;
}
return true;
}
/**
* 删除文件列表
* @param fileList
* @return
*/
public boolean deleteFiles(String[] fileList){
try{
//获取客户端连接
AmazonS3 s3Client = this.createS3Client(accessKeyId,secretAccessKey,endPoint);
//删除多个文件
DeleteObjectsRequest deleteObjectsRequest = new DeleteObjectsRequest(bucketName).withKeys(fileList);
s3Client.deleteObjects(deleteObjectsRequest);
}catch (Exception e){
log.error(e);
return false;
}
return true;
}
/**
* 查找桶内文件是否存在
* @param fileKey
* @return
*/
public boolean exist(String fileKey){
//获取客户端连接
AmazonS3 s3Client = this.createS3Client(accessKeyId,secretAccessKey,endPoint);
ListObjectsV2Result listObjectsV2Result = s3Client.listObjectsV2(bucketName, fileKey);
return listObjectsV2Result.getKeyCount()>0;
}
/**
* 根据prefix获取文件列表
* 注意:若不进行do-while,只进行一次s3Client.listObjectsV2(req),则最多展示1000条
* @param prefix
* @return
*/
public List<S3ObjectSummary> searchPathFileByPrefix(String prefix){
ArrayList<S3ObjectSummary> returnList = new ArrayList<>();
try{
//获取客户端连接
AmazonS3 s3Client = this.createS3Client(accessKeyId,secretAccessKey,endPoint);
//按prefix获取文件列表
ListObjectsV2Request req = new ListObjectsV2Request().withBucketName(bucketName);
ListObjectsV2Result result;
if(prefix!=null &&!prefix.isEmpty()){
req = req.withPrefix(prefix);
}
do{
result = s3Client.listObjectsV2(req);
returnList.addAll(result.getObjectSummaries());
String token = result.getNextContinuationToken();
req.setContinuationToken(token);
}while(result.isTruncated());
return returnList;
}catch (Exception e){
log.error(e);
return null;
}
}
/**
* 生成文件的预签名URL
* 注意:
* 1.有url,无需通过密钥连接对象存储桶,只用http请求就能下载文件
* 2.url最多7天有效,官方限制。所以必须考虑url刷新
* @param fileKey
* @return
*/
public String generalUrl(String fileKey){
try{
//获取客户端连接
AmazonS3 s3Client = this.createS3Client(accessKeyId,secretAccessKey,endPoint);
//设置预签名失效时间-最多七天
Calendar calendar = Calendar.getInstance();
calendar.setTime(new Date());
calendar.add(Calendar.DAY_OF_MONTH,7);
Date date = calendar.getTime();
//生成预签名链接
GeneratePresignedUrlRequest generatePresignedUrlRequest = new GeneratePresignedUrlRequest(bucketName, fileKey)
.withMethod(HttpMethod.GET)
.withExpiration(date);
URL url = s3Client.generatePresignedUrl(generatePresignedUrlRequest);
return url.toString();
}catch (Exception e){
log.error(e);
return null;
}
}
/**
* 根据url下载文件到本地
* @param url
* @param filePath
* @return
* @throws IOException
*/
public File downloadFromUrl(String url,String filePath) throws IOException {
//获取文件名
String tmpUrl = StringUtils.substring(url,url.indexOf("//")+2);
int startPos = StringUtils.indexOf(tmpUrl,"/",tmpUrl.indexOf("/")+1)+1;
int endPos = StringUtils.indexOf(tmpUrl,"?");
tmpUrl = StringUtils.substring(tmpUrl,startPos,endPos);
String fileName = Paths.get(StringUtils.replace(tmpUrl,"%2F","/")).getFileName().toString();
//http请求
HttpClient client = HttpClients.createDefault();
HttpGet httpGet = new HttpGet(url);
HttpResponse response = client.execute(httpGet);
HttpEntity entity = response.getEntity();
//输出文件
File file = new File(filePath + "/" + fileName);
if(!file.getParentFile().exists()&&!file.getParentFile().isDirectory()){
file.getParentFile().mkdir();
}
try(InputStream is = entity.getContent();
FileOutputStream fileout = new FileOutputStream(file)){
byte[] buffer = new byte[10 * 1024];
int ch = 0;
while((ch = is.read(buffer))!=-1){
fileout.write(buffer,0,ch);
}
fileout.flush();
return file;
}catch (Exception e){
return null;
}
}
}
四、总结:
Amazon s3可以替代nas进行文件存储,在分布式架构中非常适用。
除了以上基础的使用外,还有分片下载、断点续传、异常处理等场景以及s3Browser工具的使用,后续进行分享。
PS:若有错漏,欢迎大家指正与讨论,谢谢~
版权归原作者 RiceFragrant 所有, 如有侵权,请联系我们删除。