Spring Boot 集成 AmazonS3 存储服务教程
原文链接:https://www.changxuan.top/?p=963
环境准备
- Java环境:JDK6以上版本
- SpringBoot 2.2.5
- 存储服务的 accessKey、secreKey 以及 地址:端口
使用
1. 引入依赖
在 pom.xml
文件中添加下列依赖:
<dependency><groupId>com.amazonaws</groupId><artifactId>aws-java-sdk</artifactId><version>1.11.433</version>
</dependency>
2. 初始化
> 简单模式
String accessKey = "your-accesskey";
String secretKey = "your-secretKey";AWSCredentials credentials = new BasicAWSCredentials(accessKey, secretKey);
AmazonS3 conn = AmazonS3ClientBuilder.standard().withCredentials(new AWSStaticCredentialsProvider(credentials)).withEndpointConfiguration(new AwsClientBuilder.EndpointConfiguration("endpoint","region")).build();
示例:
String accessKey = "TPDDEA5PCT9C8RUPKAWW";
String secretKey = "ryesPMSiSfOzaP1TkFe9TIOBnxpdrA2sw6isFwDZ";AWSCredentials credentials = new BasicAWSCredentials(accessKey, secretKey);
AmazonS3 conn = AmazonS3ClientBuilder.standard().withCredentials(new AWSStaticCredentialsProvider(credentials)).withEndpointConfiguration(new AwsClientBuilder.EndpointConfiguration("http://10.200.100.37:7480","region")).build();
> 配置模式
import com.amazonaws.ClientConfiguration;
import com.amazonaws.Protocol;
import com.amazonaws.auth.AWSCredentials;
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;String accessKey = "your-accesskey";
String secretKey = "your-secretKey ";
AWSCredentials credentials = new BasicAWSCredentials(accessKey,secretKey);
ClientConfiguration conf = new ClientConfiguration();
// 设置AmazonS3使用的最大连接数
conf.setMaxConnections(200);
// 设置socket超时时间
conf.setSocketTimeout(10000);
// 设置失败请求重试次数
conf.setMaxErrorRetry(2);
// 如果要用https协议,请加上下面语句
conf.setProtocol(Protocol.HTTPS);//AmazonS3 s3Client = new AmazonS3Client(credentials,clientConfiguration);
//s3Client.setEndpoint(endPoint);
AmazonS3 s3Client = AmazonS3ClientBuilder.standard().withCredentials(new AWSStaticCredentialsProvider(credentials)).withEndpointConfiguration(new AwsClientBuilder.EndpointConfiguration("endpoint","region")).withClientConfiguration(conf).build();//endpoint,region请指定为NOS支持的
示例:
Amazon3 是线程安全的,因此可以将其注入到 Spring 容器中进行管理。
@AmazonS3Config.java
import com.amazonaws.ClientConfiguration;
import com.amazonaws.Protocol;
import com.amazonaws.auth.AWSCredentials;
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.CreateBucketRequest;
import com.amazonaws.services.s3.transfer.TransferManager;
import com.amazonaws.services.s3.transfer.TransferManagerBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;/*** @Author: ChangXuan* @Decription: 初始化AmazonS3实例* @Date: 17:33 2020/6/3**/
@Configuration
@EnableConfigurationProperties(UploadConfig.class)
public class AmazonS3Config {@Autowiredprivate UploadConfig uploadConfig;@Bean(name = "amazonS3")public AmazonS3 getAmazonS3(){String accessKey = uploadConfig.getCeph().getAccessKey();String secretKey = uploadConfig.getCeph().getSecretKey();AWSCredentials credentials = new BasicAWSCredentials(accessKey,secretKey);ClientConfiguration conf = new ClientConfiguration();// 设置AmazonS3使用的最大连接数conf.setMaxConnections(uploadConfig.getCeph().getAmazonS3MaxConnections());// 设置socket超时时间conf.setSocketTimeout(uploadConfig.getCeph().getAmazonS3SocketTimeout());// 设置失败请求重试次数conf.setMaxErrorRetry(uploadConfig.getCeph().getAmazonS3MaxErrorRetry());// 设置协议if (!"blank".equals(uploadConfig.getCeph().getAmazonS3Protocol())){switch (uploadConfig.getCeph().getAmazonS3Protocol()){case "https":conf.setProtocol(Protocol.HTTPS);break;case "http":conf.setProtocol(Protocol.HTTP);break;default:break;}}AmazonS3 s3Client = AmazonS3ClientBuilder.standard().withCredentials(new AWSStaticCredentialsProvider(credentials)).withEndpointConfiguration(new AwsClientBuilder.EndpointConfiguration(uploadConfig.getCeph().getHosts().get(0),uploadConfig.getCeph().getRegion())).withClientConfiguration(conf).build();checkAndCreateBucket(s3Client);return s3Client;}@Bean(name = "transferManager")public TransferManager getTransferManager(){return TransferManagerBuilder.standard().withS3Client(getAmazonS3()).build();}/*** 检查桶是否存在,不存在则创建创建* @param s3Client*/private void checkAndCreateBucket(AmazonS3 s3Client){boolean exists = s3Client.doesBucketExistV2(uploadConfig.getCeph().getBucketName());if (!exists){CreateBucketRequest request = new CreateBucketRequest(uploadConfig.getCeph().getBucketName());s3Client.createBucket(request);}}
@UploadConfig.java
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;/*** @Author: ChangXuan* @Decription: 上传 配置* @Date: 17:25 2020/6/3**/
@ConfigurationProperties(prefix = "upload")
@Data
public class UploadConfig {private CephConfig ceph;
}
@CephConfig.java
import com.google.common.collect.Lists;
import lombok.Data;import java.util.List;/*** @Author: ChangXuan* @Decription:配置* @Date: 17:28 2020/6/3**/
@Data
public class CephConfig {/*** 集群ip:port*/private List<String> hosts = Lists.newArrayList();private String accessKey;private String secretKey;private String region;/*** 连接协议*/private String amazonS3Protocol;/*** 失败请求重试次数*/private Integer amazonS3MaxErrorRetry;/*** 超时时间*/private Integer amazonS3SocketTimeout;/*** 最大连接数*/private Integer amazonS3MaxConnections;/*** 桶名称*/private String bucketName;}
@application.yml
upload:ceph:bucketName: ic-storage-devregion: regionhosts:- "10.200.100.37:7480"- "10.200.100.38:7480"- "10.200.100.39:7480"accessKey: TPDDEA5PCT9C8RUPKAWWsecretKey: ryesPMSiSfOzaP1TkFe9TIWQnxpdrA2sw6isFwDZamazonS3MaxConnections: 200amazonS3SocketTimeout: 10000amazonS3MaxErrorRetry: 2amazonS3Protocol: http
3. 依赖注入
@Autowired
private AmazonS3 amazonS3;//或@Autowired
private TransferManager transferManager;
4. 文件操作
文件上传
1. 直接内容上传
//要上传文件内容
String content = "Object content";
try {amazonS3.putObject("your-bucketname","your-objectname",content);
}catch (Exception e){System.out.println(e.getMessage());
}
2. 本地文件普通上传
对于小对象可以使用putObject接口进行上传,putObject上传支持的最大文件大小为100M,如果上传大于100M的文件需要使用分块上传。本地文件普通上传的示例代码如下:
//要上传文件的路径
String filePath = "your-local-file-path";
try {amazonS3.putObject("your-bucketname","your-objectname", new File(filePath));
}catch (Exception e){System.out.println(e.getMessage());
}
3. 上传文件时设置文件元数据信息
String filePath = "your-local-file-path";
ObjectMetadata objectMetadata = new ObjectMetadata();
//设置Content-Type
objectMetadata.setContentType("application/xml");
//设置标准http消息头(元数据)
objectMetadata.setHeader("Cache-Control", "no-cache");
//设置用户自定义元数据信息
Map<String, String> userMeta = new HashMap<String, String>();
userMeta.put("ud", "test");
objectMetadata.setUserMetadata(userMeta);
PutObjectRequest putObjectRequest = new PutObjectRequest("your-bucketname","your-objectname", new File(filePath));
putObjectRequest.setMetadata(objectMetadata);
amazonS3.putObject(putObjectRequest);
4. 流式上传
try {ObjectMetadata objectMetadata = new ObjectMetadata();//设置流的长度,您还可以设置其他文件元数据信息objectMetadata.setContentLength(streamLength);amazonS3.putObject("your-bucketname","your-objectname", inputStream, objectMetadata)
}catch (Exception e){System.out.println(e.getMessage());
}
文件下载
1. 流式下载
S3Object fileObject = amazonS3.getObject("your-bucketname","your-objectname");
//可以通过getObjectMetadata方法获取对象的ContentType等元数据信息
String contentType = fileObject.getObjectMetadata().getContentType();
//流式获取文件内容
InputStream in = fileObject.getObjectContent();
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
while (true) {String line;try {line = reader.readLine();if (line == null) break;System.out.println("\n" + line);} catch (IOException e) {e.printStackTrace();}
}
try {reader.close();
} catch (IOException e) {e.printStackTrace();
}
2. 下载到本地文件
String destinationFile = "your-local-filepath";
GetObjectRequest getObjectRequest = new GetObjectRequest("your-bucketname","your-objectname");
ObjectMetadata objectMetadata = amazonS3.getObject(getObjectRequest, new File(destinationFile));
3. Range 下载
GetObjectRequest getObjectRequest = new GetObjectRequest("your-bucketname","your-objectname");
getObjectRequest.setRange(0, 100);
S3Object nosObject = amazonS3.getObject(getObjectRequest);
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
while (true) {String line;try {line = reader.readLine();if (line == null) break;System.out.println("\n" + line);} catch (IOException e) {e.printStackTrace();}
}
try {reader.close();
} catch (IOException e) {e.printStackTrace();
}
文件管理
判断文件是否存在
您可以通过AmazonS3.doesObjectExist判断文件是否存在。
boolean isExist = amazonS3.doesObjectExist("your-bucketname","your-objectname");
文件删除
您可以通过AmazonS3.deleteObject删除单个文件
amazonS3.deleteObject("your-bucketname","your-objectname");
您还可以通过AmazonS3.deleteObjects一次删除多个文件
try {DeleteObjectsResult result = amazonS3.deleteObjects(deleteObjectsRequest);List<DeletedObject> deleteObjects = result.getDeletedObjects();//print the delete resultsfor (DeletedObject items: deleteObjects){System.out.println(items.getKey());}
// 部分对象删除失败
} catch (MultiObjectDeleteException e) { List<DeleteError> deleteErrors = e.getErrors();for (DeleteError error : deleteErrors) {System.out.println(error.getKey());}
} catch (AmazonServiceException e) {//捕捉服务器异常错误
} catch (AmazonClientException ace) {//捕捉客户端错误
}
获取文件元数据信息
您可以通过AmazonS3.getObjectMetadata获取文件元数据信息
amazonS3.getObjectMetadata("your-bucketname","your-objectname");
文件复制(copy)
您可以通过AmazonS3.copyObject接口实现文件拷贝功能。
amazonS3.copyObject("source-bucket", "source-object", "dst-bucket", "dst-object");
列举桶内文件
您可以通过AmazonS3.listObjects列出桶里的文件。listObjects接口如果调用成功,会返回一个ObjectListing对象,列举的结果保持在该对象中。
ObjectListing的具体信息如下表所示:
方法 | 含义 |
---|---|
List getObjectSummaries() | 返回的文件列表(包含文件的名称、Etag的元数据信息) |
String getPrefix() | 本次查询的文件名前缀 |
String getDelimiter() | 文件分界符 |
String getMarker() | 这次List Objects的起点 |
int getMaxKeys() | 响应请求内返回结果的最大数目 |
String getNextMarker() | 下一次List Object的起点 |
boolean isTruncated() | 是否截断,如果因为设置了limit导致不是所有的数据集都返回,则该值设置为true |
List getCommonPrefixes() | 如果请求中指定了delimiter参数,则返回的包含CommonPrefixes元素。该元素标明以delimiter结尾,并有共同前缀的对象的集合 |
AmazonS3.listObjects接口提供两种调用方式:简单列举、通过ListObjectsRequest列举
简单列举
简单列举只需指定需要列举的桶名,最多返回100条对象记录,建议桶内对象数较少时(小于100)使用。
ObjectListing objectListing = amazonS3.listObjects("your-bucketname");
List<S3ObjectSummary> sums = objectListing.getObjectSummaries();
for (S3ObjectSummary s : sums) {System.out.println("\t" + s.getKey());
}
通过ListObjectsRequest列举
您还可以通过设置ListObjectsReques参数实现各种灵活的查询功能。ListObjectsReques的可设置的参数如下:
设置方法 | 作用 |
---|---|
setPrefix(String prefix) | 限定返回的object key必须以prefix作为前缀 |
setDelimiter(String delimiter) | 是一个用于对Object名字进行分组的字符。所有名字包含指定的前缀且第一次出现delimiter字符之间的object作为一组元素——CommonPrefixes |
setMarker(String marker) | 字典序的起始标记,只列出该标记之后的部分 |
setMaxKeys(Integer maxKeys) | 限定返回的数量,返回的结果小于或等于该值(默认值为100) |
1、分页列举桶内的所有文件:
List<S3ObjectSummary> listResult = new ArrayList<S3ObjectSummary>();
ListObjectsRequest listObjectsRequest = new ListObjectsRequest();
listObjectsRequest.setBucketName("your-bucketname");
listObjectsRequest.setMaxKeys(50);
ObjectListing listObjects = amazonS3.listObjects(listObjectsRequest);
do {listResult.addAll(listObjects.getObjectSummaries());if (listObjects.isTruncated()) {ListObjectsRequest request = new ListObjectsRequest();request.setBucketName(listObjectsRequest.getBucketName());request.setMarker(listObjects.getNextMarker());listObjects = amazonS3.listObjects(request);} else {break;}
} while (listObjects != null);
2、使用Delimiter模拟文件夹功能
假设桶内有如下对象:a/1.jpg、a/2.jpg、a/b/1.txt、a/b/2.txt,列举a文件夹下的文件及子文件夹的示例代码如下:
ListObjectsRequest listObjectsRequest = new ListObjectsRequest();
listObjectsRequest.setBucketName("your-bucketname");
listObjectsRequest.setDelimiter("/");
listObjectsRequest.setPrefix("a/");
ObjectListing listing = amazonS3.listObjects(listObjectsRequest);
// 遍历所有Object
System.out.println("Objects:");
for (S3ObjectSummary objectSummary : listing.getObjectSummaries()) {System.out.println(objectSummary.getKey());
}
// 遍历所有CommonPrefix
System.out.println("CommonPrefixs:");
for (String commonPrefix : listing.getCommonPrefixes()) {System.out.println(commonPrefix);
}
示例代码的输出如下:
Objects:
a/1.jpg
a/2.jpg
CommonPrefixs:
a/b/
生成私有对象可下载的URL链接
AWS Java SDK支持生成可下载私有对象的URL连接,您可以将该链接提供给第三方进行文件下载:
GeneratePresignedUrlRequest generatePresignedUrlRequest = new GeneratePresignedUrlRequest(bucketName, key);
// 设置可下载URL的过期时间为1天后
generatePresignedUrlRequest.setExpiration(new Date(System.currentTimeMillis()+3600*1000*24));
URL url = amazonS3.generatePresignedUrl(generatePresignedUrlRequest);//生成URL
System.out.println(url);//可以用这个url来下载文件
文件上传下载工具类 TransferManager
前文提到的是 Java SDK提供的基础接口,为方便用户进行文件上传下载,Java SDK提供了封装更好、使用更方便的工具类:TransferManager。
TransferManager的初始化
注:在 SpringBoot 项目中 TransferManager 的初始化 参考上述 [配置模式](#### 配置模式)
//先实例化一个AmazonS3
String accessKey = "your-accesskey";
String secretKey = "your-secretKey ";
Credentials credentials = new BasicCredentials(accessKey, secretKey);
AmazonS3 amazonS3 = new AmazonS3(credentials);
amazonS3.setEndpoint(endPoint);
//然后通过AmazonS3对象来初始化TransferManager
TransferManager transferManager = new TransferManager(amazonS3);
Download download = transferManager.download(TestConfig.bucketName,key,new File("localFilePath"));
try {download.waitForCompletion();
} catch (InterruptedException e) {e.printStackTrace();
}
使用TransferManager进行文件上传
TransferManager会根据文件大小,选择是否进行分块上传。当文件小于等于16M时,TransferManager会自动调用PutObject接口,否则TransferManager会自动对文件进行分块上传。
1、上传本地文件:
如果指定上传的本地文件大于16M,TransferManager会自动对文件进行分块,并发调用分块上传接口进行上传,大大提高上传文件的速度。
//上传文件
Upload upload = transferManager.upload("your-bucketname", "your-objectname", new File("your-file"));
try {upload.waitForUploadResult();
} catch (InterruptedException e) {e.printStackTrace();
}
2、流式上传:
您也可以使用TransferManager进行流式上传,但是相比本地文件上传,流式上传无法做到多个分块并发上传,只能一个分块一个分块顺序上传。
//流式上传文件
ObjectMetadata objectMetadata = new ObjectMetadata();
objectMetadata.setContentLength(file.length());
Upload upload = transferManager.upload("your-bucketname", "your-objectname", inputStream, objectMetadata);
UploadResult result = upload.waitForUploadResult();
3、上传目录
您可以使用TransferManager将某个目录下的文件全部上传到NOS,对象名即文件名
- 3.1 不支持多级目录
MultipleFileUpload result = transferManager.uploadDirectory("your-buckename", null, new File("dirPath"), false);
result.waitForCompletion();
- 3.2 支持多级目录,会递归的上传目录下的所有文件
MultipleFileUpload result = transferManager.uploadDirectory("your-buckename", null, new File("dirPath"), true);
result.waitForCompletion();
4、下载文件
File file = new File("your-destFile");
Download download = transferManager.download("your-bucketname", "your-objectname", file);
download.waitForCompletion();
参考资料
[1] 网易数帆S3 Java SDK 手册
Spring Boot 集成 AmazonS3 存储服务教程相关推荐
- Spring Boot教程(十六):Spring Boot集成shiro
Apache Shiro™是一个功能强大且易于使用的Java安全框架,可执行身份验证,授权,加密和会话管理.借助Shiro易于理解的API,您可以快速轻松地保护任何应用程序 - 从最小的移动应用程序到 ...
- Spring Boot集成阿里云视频点播服务的过程记录
阿里云视频点播 效果预览 视频点播 视频点播概述 功能 优势 流程 环境准备 开通视频点播 创建RAM用户并授权 上传SDK 上传流程 下载上传SDK 安装上传SDK 集成Java上传SDK 异常说明 ...
- Spring boot集成axis2开发webservice 服务
Spring boot集成axis2开发webservice 服务 1.新建Spring boot 项目 此处省略... 项目结构如下: 2.添加Axis2依赖 <!--axis2版本信息--& ...
- Spring Boot+gRPC构建微服务并部署到Istio(详细教程)
点击关注公众号,实用技术文章及时了解 作为Service Mesh和云原生技术的忠实拥护者,我却一直没有开发过Service Mesh的应用.正好最近受够了Spring Cloud的"折磨& ...
- SpringBoot2.x系列教程(四十五)Spring Boot集成WebSocket实现技术交流群功能
在上篇文章中,我们了解了WebSocket的基本功能及相关概念.本篇文章中我们以具体的实例来演示,在Spring Boot中整合WebSocket,同时实现一个场景的业务场景功能. 针对在Spring ...
- 五分钟学会 Spring Boot Admin:微服务应用监控(小白必看,一看就会教程)
Spring Boot Admin:微服务应用监控 Spring Boot Admin 简介 监控信息演示 结合注册中心使用 功能演示 添加登录认证 文末福利 Spring Boot Admin 可以 ...
- 《Spring Boot极简教程》第8章 Spring Boot集成Groovy,Grails开发
第8章 Spring Boot集成Groovy,Grails开发 本章介绍Spring Boot集成Groovy,Grails开发.我们将开发一个极简版的pms(项目管理系统). Groovy和Gra ...
- Linux 安装Redis-6.2.5,配置及使用(RDB与AOF持久化、sentinel机制、主从复制、Spring Boot 集成 Redis)
CentOS 7 安装Redis-6.2.5版本 Redis采用的是基于内存的单进程 单线程模型 的KV数据库,由C语言编写.官方提供的数据是可以达到100000+的qps 应用场景: 令牌(Toke ...
- spring boot 集成sleuth
spring boot 集成sleuth 1. 理论 1.1 sleuth是什么 1.2 sleuth有哪些 1.3 链路追踪的一些基本概念 1.4 zipkin的组成 2. zipkin 实例 2. ...
最新文章
- udev与devfs文件系统
- windows调用ubuntu下的sublimeText2环境搭建
- 结合案例深入解析策略模式
- Silverlight实用窍门系列:51.Silverlight页面控件的放大缩小、Silverlight和Html控件的互相操作...
- JQuery实现页面跳转
- centos6上安装mysql8.0版本
- 1-18Linux内核空间和用户空间
- python复制文件的代码_python调用cmd复制文件代码分享
- 详解HTML5中rel属性的prefetch预加载功能使用
- Python中对list进行排序
- POJ - 2718 Smallest Difference
- 恒德可视化指挥调度解决方案
- python改变图片像素值大小_Python之修改图片像素值的方法
- 同花顺股票交易接口 正确用法
- Python爬虫常用库requests、beautifulsoup、selenium、xpath总结
- 微软2016校园招聘4月在线笔试 hihocoder 1288 Font Size (模拟)
- aardio - 【库】webp图片转换
- 竞品分析的意义在哪?竞品分析后怎样优化店铺,竞品分析哪里找?
- Win系统如何修改远程桌面端口3389
- 新闻客户端的三种模式和四种活法
热门文章
- 微信小程序开发设置苹方字体
- 游戏原画用的是什么软件?学习难易程度怎么样?我们一起来看看吧
- oracle登录和用户的切换
- 学生党什么蓝牙耳机比较适合?500左右高人气蓝牙耳机分享
- line-height 行高
- 【Unity插件】最多的插件合集
- 英语专业应报考计算机二级哪一科目,计算机二级科目怎么选 计算机二级有哪些科目...
- 手机java软件卸载_Android系统软件卸载方法
- CSS3动画进阶:tranform与keyframes 组合动画
- c++做界面_Adobe Photoshop基本介绍②,快速入门界面