原文链接:https://www.changxuan.top/?p=963

环境准备

  1. Java环境:JDK6以上版本
  2. SpringBoot 2.2.5
  3. 存储服务的 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 存储服务教程相关推荐

  1. Spring Boot教程(十六):Spring Boot集成shiro

    Apache Shiro™是一个功能强大且易于使用的Java安全框架,可执行身份验证,授权,加密和会话管理.借助Shiro易于理解的API,您可以快速轻松地保护任何应用程序 - 从最小的移动应用程序到 ...

  2. Spring Boot集成阿里云视频点播服务的过程记录

    阿里云视频点播 效果预览 视频点播 视频点播概述 功能 优势 流程 环境准备 开通视频点播 创建RAM用户并授权 上传SDK 上传流程 下载上传SDK 安装上传SDK 集成Java上传SDK 异常说明 ...

  3. Spring boot集成axis2开发webservice 服务

    Spring boot集成axis2开发webservice 服务 1.新建Spring boot 项目 此处省略... 项目结构如下: 2.添加Axis2依赖 <!--axis2版本信息--& ...

  4. Spring Boot+gRPC构建微服务并部署到Istio(详细教程)

    点击关注公众号,实用技术文章及时了解 作为Service Mesh和云原生技术的忠实拥护者,我却一直没有开发过Service Mesh的应用.正好最近受够了Spring Cloud的"折磨& ...

  5. SpringBoot2.x系列教程(四十五)Spring Boot集成WebSocket实现技术交流群功能

    在上篇文章中,我们了解了WebSocket的基本功能及相关概念.本篇文章中我们以具体的实例来演示,在Spring Boot中整合WebSocket,同时实现一个场景的业务场景功能. 针对在Spring ...

  6. 五分钟学会 Spring Boot Admin:微服务应用监控(小白必看,一看就会教程)

    Spring Boot Admin:微服务应用监控 Spring Boot Admin 简介 监控信息演示 结合注册中心使用 功能演示 添加登录认证 文末福利 Spring Boot Admin 可以 ...

  7. 《Spring Boot极简教程》第8章 Spring Boot集成Groovy,Grails开发

    第8章 Spring Boot集成Groovy,Grails开发 本章介绍Spring Boot集成Groovy,Grails开发.我们将开发一个极简版的pms(项目管理系统). Groovy和Gra ...

  8. Linux 安装Redis-6.2.5,配置及使用(RDB与AOF持久化、sentinel机制、主从复制、Spring Boot 集成 Redis)

    CentOS 7 安装Redis-6.2.5版本 Redis采用的是基于内存的单进程 单线程模型 的KV数据库,由C语言编写.官方提供的数据是可以达到100000+的qps 应用场景: 令牌(Toke ...

  9. spring boot 集成sleuth

    spring boot 集成sleuth 1. 理论 1.1 sleuth是什么 1.2 sleuth有哪些 1.3 链路追踪的一些基本概念 1.4 zipkin的组成 2. zipkin 实例 2. ...

最新文章

  1. udev与devfs文件系统
  2. windows调用ubuntu下的sublimeText2环境搭建
  3. 结合案例深入解析策略模式
  4. Silverlight实用窍门系列:51.Silverlight页面控件的放大缩小、Silverlight和Html控件的互相操作...
  5. JQuery实现页面跳转
  6. centos6上安装mysql8.0版本
  7. 1-18Linux内核空间和用户空间
  8. python复制文件的代码_python调用cmd复制文件代码分享
  9. 详解HTML5中rel属性的prefetch预加载功能使用
  10. Python中对list进行排序
  11. POJ - 2718 Smallest Difference
  12. 恒德可视化指挥调度解决方案
  13. python改变图片像素值大小_Python之修改图片像素值的方法
  14. 同花顺股票交易接口 正确用法
  15. Python爬虫常用库requests、beautifulsoup、selenium、xpath总结
  16. 微软2016校园招聘4月在线笔试 hihocoder 1288 Font Size (模拟)
  17. aardio - 【库】webp图片转换
  18. 竞品分析的意义在哪?竞品分析后怎样优化店铺,竞品分析哪里找?
  19. Win系统如何修改远程桌面端口3389
  20. 新闻客户端的三种模式和四种活法

热门文章

  1. 微信小程序开发设置苹方字体
  2. 游戏原画用的是什么软件?学习难易程度怎么样?我们一起来看看吧
  3. oracle登录和用户的切换
  4. 学生党什么蓝牙耳机比较适合?500左右高人气蓝牙耳机分享
  5. line-height 行高
  6. 【Unity插件】最多的插件合集
  7. 英语专业应报考计算机二级哪一科目,计算机二级科目怎么选 计算机二级有哪些科目...
  8. 手机java软件卸载_Android系统软件卸载方法
  9. CSS3动画进阶:tranform与keyframes 组合动画
  10. c++做界面_Adobe Photoshop基本介绍②,快速入门界面