目前只实现了 S3 的存储,提供同步和异步两种操作接口。
AWS 凭证提供者
S3 存储模块依赖 AWS 凭证提供者来认证访问。框架提供了两个版本的凭证提供者,分别对应 AWS SDK v1 和 v2。
AWS SDK v1 凭证提供者
提供 AWSCredentialsProvider Bean,供 S3 v1 及其他 AWS SDK v1 模块使用。
仓库坐标
<dependency>
<groupId>com.luamas.thinkbridge</groupId>
<artifactId>aws-spring-boot-starter</artifactId>
</dependency>
implementation("com.luamas.thinkbridge:aws-spring-boot-starter")
配置
think:
aws:
# 是否启用,默认启用
enable: true
# AWS Access Key ID
access-key-id: 'TODO key'
# AWS Secret Access Key
secret-access-key-id: 'TODO'
AWS SDK v2 凭证提供者
提供 AwsCredentialsProvider Bean,供 S3 v2 及其他 AWS SDK v2 模块使用。
仓库坐标
<dependency>
<groupId>com.luamas.thinkbridge</groupId>
<artifactId>aws-v2-spring-boot-starter</artifactId>
</dependency>
implementation("com.luamas.thinkbridge:aws-v2-spring-boot-starter")
同步接口
package com.luamas.thinkbridge.common.upload.service;
import org.apache.commons.lang3.time.DateFormatUtils;
import java.io.File;
import java.io.InputStream;
import java.io.OutputStream;
import java.time.Duration;
import java.util.Date;
import java.util.Map;
/
* 文件上传下载接口
/
public interface UploadService {
String DATE_PATH = "yyyy/MM/dd";
String CONTENT_TYPE = "Content-Type";
String CONTENT_LENGTH = "Content-Length";
String CONTENT_MD5 = "Content-MD5";
String ETAG = "ETag";
/
* 获取文件md5值
* @return
*/
default String getContentMd5(String bucket, String fullFilePath) {
if (getFileHeaders(bucket, fullFilePath).containsKey(CONTENT_MD5)) {
return (String) getFileHeaders(bucket, fullFilePath).get(CONTENT_MD5);
}
return null;
}
default String getContentMd5(String fullFilePath) {
return getContentMd5(null, fullFilePath);
}
/
* 获取文件类型
* @return
*/
default String getContentType(String bucket, String fullFilePath) {
if (getFileHeaders(bucket, fullFilePath).containsKey(CONTENT_TYPE)) {
return (String) getFileHeaders(bucket, fullFilePath).get(CONTENT_TYPE);
}
return null;
}
default String getContentType(String fullFilePath) {
return getContentType(null, fullFilePath);
}
/
* 获取文件长度
* @return
*/
default String getContentLength(String bucket, String fullFilePath) {
if (getFileHeaders(bucket, fullFilePath).containsKey(CONTENT_LENGTH)) {
return (String) getFileHeaders(bucket, fullFilePath).get(CONTENT_LENGTH);
}
return null;
}
default String getContentLength(String fullFilePath) {
return getContentLength(null, fullFilePath);
}
/
* 获取文件etag,hash值
* @return
*/
default String getEtag(String bucket, String fullFilePath) {
if (getFileHeaders(bucket, fullFilePath).containsKey(ETAG)) {
return (String) getFileHeaders(bucket, fullFilePath).get(ETAG);
}
return null;
}
default String getEtag(String fullFilePath) {
return getEtag(null, fullFilePath);
}
default Map<String, Object> getFileHeaders(String fullFilePath) {
return getFileHeaders(null, fullFilePath);
}
Map<String, Object> getFileHeaders(String bucket, String fullFilePath);
/
* 缓存路径
* @return
*/
default String tempPath() {
String filePath = "temp" +
"/" +
DateFormatUtils.format(new Date(), DATE_PATH);
return filePath;
}
/
* 文件上传
* @param bucket 桶
* @param inputStream 文件流
* @param filePath 文件路径
* @param fileName 文件名
* @param isOpenUrl url是否为开放状态
* @return
*/
String upload(final String bucket, final InputStream inputStream, final String filePath, final String fileName, final boolean isOpenUrl);
/
* 文件上传
* @param inputStream 文件流
* @param filePath 文件路径
* @param fileName 文件名
* @param isOpenUrl url是否为开放状态
* @return
*/
default String upload(final InputStream inputStream, final String filePath, final String fileName, final boolean isOpenUrl) {
return upload(null, inputStream, filePath, fileName, isOpenUrl);
}
/
* 上传私有文件
* @param inputStream 文件流
* @param filePath 文件路径
* @param fileName 文件名
* @return
*/
default String upload(final InputStream inputStream, final String filePath, final String fileName) {
return upload(inputStream, filePath, fileName, false);
}
/
* 上传私有文件
* @param inputStream 文件流
* @param fileName 文件名
* @return
*/
default String upload(final InputStream inputStream, final String fileName) {
return upload(inputStream, null, fileName);
}
/
* 文件上传
* @param bucket 桶
* @param file 文件
* @param filePath 文件路径
* @param fileName 文件名
* @param isOpenUrl url是否为开放状态
* @return
*/
String upload(final String bucket, final File file, final String filePath, final String fileName, final boolean isOpenUrl);
/
* 文件上传
* @param file 文件
* @param filePath 文件路径
* @param fileName 文件名
* @param isOpenUrl url是否为开放状态
* @return
*/
default String upload(final File file, final String filePath, final String fileName, final boolean isOpenUrl) {
return upload(null, file, filePath, fileName, isOpenUrl);
}
/
* 上传私有文件
* @param file 文件
* @param filePath 文件路径
* @param fileName 文件名
* @return
*/
default String upload(final File file, final String filePath, final String fileName) {
return upload(file, filePath, fileName, false);
}
/
* 上传私有文件
* @param file 文件
* @param fileName 文件名
* @return
*/
default String upload(final File file, final String fileName) {
return upload(file, null, fileName);
}
/
* 根据路径获取url
* @param bucket 桶
* @param fullFilePath
* @param timeToLive 文件上传后获取url的有效期
* @param isOpenUrl 开放
* @return timeToLive有效期的url
*/
String getUrl(final String bucket, final String fullFilePath, final Duration timeToLive, final boolean isOpenUrl);
/
* 根据路径获取url
* @param bucket 桶
* @param fullFilePath
* @return timeToLive有效期的url
*/
default String getOpenUrl(final String bucket, final String fullFilePath) {
return getUrl(bucket, fullFilePath, null, true);
}
/
* 根据路径获取url
* @param bucket 桶
* @param fullFilePath
* @param timeToLive 文件上传后获取url的有效期
* @return timeToLive有效期的url
*/
default String getUrl(final String bucket, final String fullFilePath, final Duration timeToLive) {
return getUrl(bucket, fullFilePath, timeToLive, false);
}
/
* 根据路径获取url
* @param fullFilePath
* @param timeToLive 文件上传后获取url的有效期
* @return timeToLive有效期的url
*/
default String getUrl(final String fullFilePath, final Duration timeToLive) {
return getUrl(null, fullFilePath, timeToLive);
}
/
* 根据路径获取url
* @param fullFilePath 全路径
* @return 默认为一小时的有效期的url
*/
default String getUrl(final String fullFilePath) {
return getUrl(fullFilePath, null);
}
/
* 删除文件
* @param bucket 桶
* @param fullFilePath
*/
void delete(final String bucket, final String fullFilePath);
/
* 删除文件
* @param fullFilePath
*/
default void delete(final String fullFilePath) {
delete(null, fullFilePath);
}
/
* 下载文件到指定路径
* @param bucket 桶
* @param fullFilePath 远程全路径
* @param localFullFilePath 本地全路径
*/
void download(final String bucket, final String fullFilePath, final String localFullFilePath);
/
* 下载文件到指定路径
* @param fullFilePath 远程全路径
* @param localFullFilePath 本地全路径
*/
default void download(final String fullFilePath, final String localFullFilePath) {
download(null, fullFilePath, localFullFilePath);
}
/
* 下载文件到输出流
* @param bucket 桶
* @param fullFilePath 远程全路径
* @param outputStream 输出流
*/
void download(final String bucket, final String fullFilePath, final OutputStream outputStream);
/
* 下载文件到输出流
* @param fullFilePath 远程全路径
* @param outputStream 输出流
*/
default void download(final String fullFilePath, final OutputStream outputStream) {
download(null, fullFilePath, outputStream);
}
/
* 文件上传
* @param file 文件
* @param filePath 文件路径
* @param fileName 文件名
* @return 默认为一小时的有效期的url
*/
default String uploadFile(final File file, final String filePath, final String fileName) {
return uploadFile(file, filePath, fileName, null);
}
/
* 文件上传
* @param file 文件
* @param filePath 文件路径
* @param fileName 文件名
* @param timeToLive 文件上传后获取url的有效期
* @return timeToLive有效期的url
*/
default String uploadFile(final File file, final String filePath, final String fileName, final Duration timeToLive) {
String key = upload(file, filePath, fileName);
return getUrl(key, timeToLive);
}
/
* 文件上传
* @param inputStream 文件流
* @param filePath 文件路径
* @param fileName 文件名
* @return 默认为一小时的有效期的url
*/
default String uploadFile(final InputStream inputStream, final String filePath, final String fileName) {
return uploadFile(inputStream, filePath, fileName, null);
}
/
* 文件上传
* @param inputStream 文件流
* @param filePath 文件路径
* @param fileName 文件名
* @param timeToLive 文件上传后获取url的有效期
* @return timeToLive有效期的url
*/
default String uploadFile(final InputStream inputStream, final String filePath, String fileName, final Duration timeToLive) {
String key = upload(inputStream, filePath, fileName);
return getUrl(key, timeToLive);
}
/
* 文件上传至temp文件夹,temp默认为临时目录,为了将来更好清理
* @param fileName 文件名
* @return 默认为一小时的有效期的url
*/
default String uploadTempFile(final File file, final String fileName) {
return uploadTempFile(file, fileName, null);
}
/
* 文件上传至temp文件夹,temp默认为临时目录,为了将来更好清理
* @param file 文件
* @param fileName 文件名
* @param timeToLive 文件上传后获取url的有效期
* @return timeToLive有效期的url
*/
default String uploadTempFile(final File file, final String fileName, final Duration timeToLive) {
String key = upload(file, tempPath(), fileName);
return getUrl(key, timeToLive);
}
/
* 文件上传至temp文件夹,temp默认为临时目录,为了将来更好清理
* @param inputStream 文件流
* @param fileName 文件名
* @return 默认为一小时的有效期的url
*/
default String uploadTempFile(final InputStream inputStream, final String fileName) {
return uploadTempFile(inputStream, fileName, null);
}
/
* 文件上传至temp文件夹,temp默认为临时目录,为了将来更好清理
* @param inputStream 文件流
* @param fileName 文件名
* @param timeToLive 文件上传后获取url的有效期
* @return timeToLive有效期的url
*/
default String uploadTempFile(final InputStream inputStream, final String fileName, final Duration timeToLive) {
String key = upload(inputStream, tempPath(), fileName);
return getUrl(key, timeToLive);
}
/
* 文件上上传且url地址为开放状态
* @param file 文件
* @param filePath 文件路径
* @param fileName 文件名
* @return
*/
default String uploadCanReadFile(final File file, final String filePath, final String fileName) {
return uploadCanReadFile(file, filePath, fileName, null);
}
/
* 文件上上传且url地址为开放状态
* @param file 文件
* @param filePath 文件路径
* @param fileName 文件名
* @param timeToLive 文件上传后获取url的有效期 ,暂时无效
* @return timeToLive有效期的url
*/
default String uploadCanReadFile(final File file, final String filePath, final String fileName, final Duration timeToLive) {
String key = upload(file, filePath, fileName, true);
return getUrl(key, timeToLive);
}
/
* 文件上上传且url地址为开放状态
* @param inputStream 文件流
* @param filePath 文件路径
* @param fileName 文件名
* @return timeToLive有效期的url
*/
default String uploadCanReadFile(final InputStream inputStream, final String filePath, final String fileName) {
return uploadCanReadFile(inputStream, filePath, fileName, null);
}
/
* 文件上上传且url地址为开放状态
* @param inputStream 文件流
* @param filePath 文件路径
* @param fileName 文件名
* @param timeToLive 文件上传后获取url的有效期 ,暂时无效
* @return timeToLive有效期的url
*/
default String uploadCanReadFile(final InputStream inputStream, final String filePath, final String fileName, final Duration timeToLive) {
String key = upload(inputStream, filePath, fileName, true);
return getUrl(key, timeToLive);
}
/
* 文件上上传且url地址为开放状态
* @param file 文件
* @param fileName 文件名
* @return
*/
default String uploadCanReadTempFile(final File file, final String fileName) {
return uploadCanReadTempFile(file, fileName, null);
}
/
* 文件上上传且url地址为开放状态
* @param file 文件
* @param fileName 文件名
* @param timeToLive 文件上传后获取url的有效期 ,暂时无效
* @return
*/
default String uploadCanReadTempFile(final File file, final String fileName, final Duration timeToLive) {
String key = upload(file, tempPath(), fileName);
return getUrl(key, timeToLive);
}
/
* 文件上上传且url地址为开放状态
* @param inputStream 文件流
* @param fileName 文件名
*/
default String uploadCanReadTempFile(final InputStream inputStream, final String fileName) {
return uploadCanReadTempFile(inputStream, fileName, null);
}
/*
* 文件上上传且url地址为开放状态
* @param inputStream 文件流
* @param fileName 文件名
* @param timeToLive 文件上传后获取url的有效期 ,暂时无效
* @return
*/
default String uploadCanReadTempFile(final InputStream inputStream, final String fileName, final Duration timeToLive) {
String key = upload(inputStream, tempPath(), fileName);
return getUrl(key, timeToLive);
}
}
异步接口
| 异步接口只有 S3 v2 包支持。 |
package com.luamas.thinkbridge.common.upload.service;
import org.apache.commons.lang3.time.DateFormatUtils;
import java.io.File;
import java.io.InputStream;
import java.io.OutputStream;
import java.time.Duration;
import java.util.Date;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
/
* 文件上传下载接口
/
public interface AsyncUploadService {
String DATE_PATH = "yyyy/MM/dd";
String CONTENT_TYPE = "Content-Type";
String CONTENT_LENGTH = "Content-Length";
String CONTENT_MD5 = "Content-MD5";
String ETAG = "ETag";
/
* 获取文件md5值
* @return
*/
default CompletableFuture<String> getContentMd5(String bucket, String fullFilePath) {
return getFileHeaders(bucket, fullFilePath).thenApply(headers -> {
if (headers.containsKey(CONTENT_MD5)) {
return (String) headers.get(CONTENT_MD5);
}
return null;
});
}
default CompletableFuture<String> getContentMd5(String fullFilePath) {
return getContentMd5(null, fullFilePath);
}
/
* 获取文件类型
* @return
*/
default CompletableFuture<String> getContentType(String bucket, String fullFilePath) {
return getFileHeaders(bucket, fullFilePath).thenApply(headers -> {
if (headers.containsKey(CONTENT_TYPE)) {
return (String) headers.get(CONTENT_TYPE);
}
return null;
});
}
default CompletableFuture<String> getContentType(String fullFilePath) {
return getContentType(null, fullFilePath);
}
/
* 获取文件长度
* @return
*/
default CompletableFuture<String> getContentLength(String bucket, String fullFilePath) {
return getFileHeaders(bucket, fullFilePath).thenApply(headers -> {
if (headers.containsKey(CONTENT_LENGTH)) {
return (String) headers.get(CONTENT_LENGTH);
}
return null;
});
}
default CompletableFuture<String> getContentLength(String fullFilePath) {
return getContentLength(null, fullFilePath);
}
/
* 获取文件etag,hash值
* @return
*/
default CompletableFuture<String> getEtag(String bucket, String fullFilePath) {
return getFileHeaders(bucket, fullFilePath).thenApply(headers -> {
if (headers.containsKey(ETAG)) {
return (String) headers.get(ETAG);
}
return null;
});
}
default CompletableFuture<String> getEtag(String fullFilePath) {
return getEtag(null, fullFilePath);
}
default CompletableFuture<Map<String, Object>> getFileHeaders(String fullFilePath) {
return getFileHeaders(null, fullFilePath);
}
CompletableFuture<Map<String, Object>> getFileHeaders(String bucket, String fullFilePath);
/
* 缓存路径
* @return
*/
default String tempPath() {
String filePath = "temp" +
"/" +
DateFormatUtils.format(new Date(), DATE_PATH);
return filePath;
}
/
* 文件上传
* @param bucket 桶
* @param inputStream 文件流
* @param filePath 文件路径
* @param fileName 文件名
* @param isOpenUrl url是否为开放状态
* @return
*/
CompletableFuture<String> upload(final String bucket, final InputStream inputStream, final String filePath, final String fileName, final boolean isOpenUrl);
/
* 文件上传
* @param inputStream 文件流
* @param filePath 文件路径
* @param fileName 文件名
* @param isOpenUrl url是否为开放状态
* @return
*/
default CompletableFuture<String> upload(final InputStream inputStream, final String filePath, final String fileName, final boolean isOpenUrl) {
return upload(null, inputStream, filePath, fileName, isOpenUrl);
}
/
* 上传私有文件
* @param inputStream 文件流
* @param filePath 文件路径
* @param fileName 文件名
* @return
*/
default CompletableFuture<String> upload(final InputStream inputStream, final String filePath, final String fileName) {
return upload(inputStream, filePath, fileName, false);
}
/
* 上传私有文件
* @param inputStream 文件流
* @param fileName 文件名
* @return
*/
default CompletableFuture<String> upload(final InputStream inputStream, final String fileName) {
return upload(inputStream, null, fileName);
}
/
* 文件上传
* @param bucket 桶
* @param file 文件
* @param filePath 文件路径
* @param fileName 文件名
* @param isOpenUrl url是否为开放状态
* @return
*/
CompletableFuture<String> upload(final String bucket, final File file, final String filePath, final String fileName, final boolean isOpenUrl);
/
* 文件上传
* @param file 文件
* @param filePath 文件路径
* @param fileName 文件名
* @param isOpenUrl url是否为开放状态
* @return
*/
default CompletableFuture<String> upload(final File file, final String filePath, final String fileName, final boolean isOpenUrl) {
return upload(null, file, filePath, fileName, isOpenUrl);
}
/
* 上传私有文件
* @param file 文件
* @param filePath 文件路径
* @param fileName 文件名
* @return
*/
default CompletableFuture<String> upload(final File file, final String filePath, final String fileName) {
return upload(file, filePath, fileName, false);
}
/
* 上传私有文件
* @param file 文件
* @param fileName 文件名
* @return
*/
default CompletableFuture<String> upload(final File file, final String fileName) {
return upload(file, null, fileName);
}
/
* 根据路径获取url
* @param bucket 桶
* @param fullFilePath
* @param timeToLive 文件上传后获取url的有效期
* @param isOpenUrl 开放
* @return timeToLive有效期的url
*/
String getUrl(final String bucket, final String fullFilePath, final Duration timeToLive, final boolean isOpenUrl);
/
* 根据路径获取url
* @param bucket 桶
* @param fullFilePath
* @return timeToLive有效期的url
*/
default String getOpenUrl(final String bucket, final String fullFilePath) {
return getUrl(bucket, fullFilePath, null, true);
}
/
* 根据路径获取url
* @param bucket 桶
* @param fullFilePath
* @param timeToLive 文件上传后获取url的有效期
* @return timeToLive有效期的url
*/
default String getUrl(final String bucket, final String fullFilePath, final Duration timeToLive) {
return getUrl(bucket, fullFilePath, timeToLive, false);
}
/
* 根据路径获取url
* @param fullFilePath
* @param timeToLive 文件上传后获取url的有效期
* @return timeToLive有效期的url
*/
default String getUrl(final String fullFilePath, final Duration timeToLive) {
return getUrl(null, fullFilePath, timeToLive);
}
/
* 根据路径获取url
* @param fullFilePath 全路径
* @return 默认为一小时的有效期的url
*/
default String getUrl(final String fullFilePath) {
return getUrl(fullFilePath, null);
}
/
* 删除文件
* @param bucket 桶
* @param fullFilePath
*/
CompletableFuture<Void> delete(final String bucket, final String fullFilePath);
/
* 删除文件
* @param fullFilePath
*/
default CompletableFuture<Void> delete(final String fullFilePath) {
return delete(null, fullFilePath);
}
/
* 下载文件到指定路径
* @param bucket 桶
* @param fullFilePath 远程全路径
* @param localFullFilePath 本地全路径
*/
CompletableFuture<Void> download(final String bucket, final String fullFilePath, final String localFullFilePath);
/
* 下载文件到指定路径
* @param fullFilePath 远程全路径
* @param localFullFilePath 本地全路径
*/
default CompletableFuture<Void> download(final String fullFilePath, final String localFullFilePath) {
return download(null, fullFilePath, localFullFilePath);
}
/
* 下载文件到输出流
* @param bucket 桶
* @param fullFilePath 远程全路径
* @param outputStream 输出流
*/
CompletableFuture<Void> download(final String bucket, final String fullFilePath, final OutputStream outputStream);
/
* 下载文件到输出流
* @param fullFilePath 远程全路径
* @param outputStream 输出流
*/
default CompletableFuture<Void> download(final String fullFilePath, final OutputStream outputStream) {
return download(null, fullFilePath, outputStream);
}
/
* 文件上传
* @param file 文件
* @param filePath 文件路径
* @param fileName 文件名
* @return 默认为一小时的有效期的url
*/
default CompletableFuture<String> uploadFile(final File file, final String filePath, final String fileName) {
return uploadFile(file, filePath, fileName, null);
}
/
* 文件上传
* @param file 文件
* @param filePath 文件路径
* @param fileName 文件名
* @param timeToLive 文件上传后获取url的有效期
* @return timeToLive有效期的url
*/
default CompletableFuture<String> uploadFile(final File file, final String filePath, final String fileName, final Duration timeToLive) {
return upload(file, filePath, fileName).thenApply(key -> getUrl(key, timeToLive));
}
/
* 文件上传
* @param inputStream 文件流
* @param filePath 文件路径
* @param fileName 文件名
* @return 默认为一小时的有效期的url
*/
default CompletableFuture<String> uploadFile(final InputStream inputStream, final String filePath, final String fileName) {
return uploadFile(inputStream, filePath, fileName, null);
}
/
* 文件上传
* @param inputStream 文件流
* @param filePath 文件路径
* @param fileName 文件名
* @param timeToLive 文件上传后获取url的有效期
* @return timeToLive有效期的url
*/
default CompletableFuture<String> uploadFile(final InputStream inputStream, final String filePath, String fileName, final Duration timeToLive) {
return upload(inputStream, filePath, fileName).thenApply(key -> getUrl(key, timeToLive));
}
/
* 文件上传至temp文件夹,temp默认为临时目录,为了将来更好清理
* @param fileName 文件名
* @return 默认为一小时的有效期的url
*/
default CompletableFuture<String> uploadTempFile(final File file, final String fileName) {
return uploadTempFile(file, fileName, null);
}
/
* 文件上传至temp文件夹,temp默认为临时目录,为了将来更好清理
* @param file 文件
* @param fileName 文件名
* @param timeToLive 文件上传后获取url的有效期
* @return timeToLive有效期的url
*/
default CompletableFuture<String> uploadTempFile(final File file, final String fileName, final Duration timeToLive) {
return upload(file, tempPath(), fileName).thenApply(key -> getUrl(key, timeToLive));
}
/
* 文件上传至temp文件夹,temp默认为临时目录,为了将来更好清理
* @param inputStream 文件流
* @param fileName 文件名
* @return 默认为一小时的有效期的url
*/
default CompletableFuture<String> uploadTempFile(final InputStream inputStream, final String fileName) {
return uploadTempFile(inputStream, fileName, null);
}
/
* 文件上传至temp文件夹,temp默认为临时目录,为了将来更好清理
* @param inputStream 文件流
* @param fileName 文件名
* @param timeToLive 文件上传后获取url的有效期
* @return timeToLive有效期的url
*/
default CompletableFuture<String> uploadTempFile(final InputStream inputStream, final String fileName, final Duration timeToLive) {
return upload(inputStream, tempPath(), fileName).thenApply(key -> getUrl(key, timeToLive));
}
/
* 文件上上传且url地址为开放状态
* @param file 文件
* @param filePath 文件路径
* @param fileName 文件名
* @return
*/
default CompletableFuture<String> uploadCanReadFile(final File file, final String filePath, final String fileName) {
return uploadCanReadFile(file, filePath, fileName, null);
}
/
* 文件上上传且url地址为开放状态
* @param file 文件
* @param filePath 文件路径
* @param fileName 文件名
* @param timeToLive 文件上传后获取url的有效期 ,暂时无效
* @return timeToLive有效期的url
*/
default CompletableFuture<String> uploadCanReadFile(final File file, final String filePath, final String fileName, final Duration timeToLive) {
return upload(file, filePath, fileName, true).thenApply(key -> getUrl(key, timeToLive));
}
/
* 文件上上传且url地址为开放状态
* @param inputStream 文件流
* @param filePath 文件路径
* @param fileName 文件名
* @return timeToLive有效期的url
*/
default CompletableFuture<String> uploadCanReadFile(final InputStream inputStream, final String filePath, final String fileName) {
return uploadCanReadFile(inputStream, filePath, fileName, null);
}
/
* 文件上上传且url地址为开放状态
* @param inputStream 文件流
* @param filePath 文件路径
* @param fileName 文件名
* @param timeToLive 文件上传后获取url的有效期 ,暂时无效
* @return timeToLive有效期的url
*/
default CompletableFuture<String> uploadCanReadFile(final InputStream inputStream, final String filePath, final String fileName, final Duration timeToLive) {
return upload(inputStream, filePath, fileName, true).thenApply(key -> getUrl(key, timeToLive));
}
/
* 文件上上传且url地址为开放状态
* @param file 文件
* @param fileName 文件名
* @return
*/
default CompletableFuture<String> uploadCanReadTempFile(final File file, final String fileName) {
return uploadCanReadTempFile(file, fileName, null);
}
/
* 文件上上传且url地址为开放状态
* @param file 文件
* @param fileName 文件名
* @param timeToLive 文件上传后获取url的有效期 ,暂时无效
* @return
*/
default CompletableFuture<String> uploadCanReadTempFile(final File file, final String fileName, final Duration timeToLive) {
return upload(file, tempPath(), fileName, true).thenApply(key -> getUrl(key, timeToLive));
}
/
* 文件上上传且url地址为开放状态
* @param inputStream 文件流
* @param fileName 文件名
*/
default CompletableFuture<String> uploadCanReadTempFile(final InputStream inputStream, final String fileName) {
return uploadCanReadTempFile(inputStream, fileName, null);
}
/*
* 文件上上传且url地址为开放状态
* @param inputStream 文件流
* @param fileName 文件名
* @param timeToLive 文件上传后获取url的有效期 ,暂时无效
* @return
*/
default CompletableFuture<String> uploadCanReadTempFile(final InputStream inputStream, final String fileName, final Duration timeToLive) {
return upload(inputStream, tempPath(), fileName, true).thenApply(key -> getUrl(key, timeToLive));
}
}
使用示例
@Resource
private UploadService uploadService;
// 上传文件
String url = uploadService.upload(inputStream, "bucket", "key", "content-type");
// 下载文件
InputStream is = uploadService.download("bucket", "key");
// 删除文件
uploadService.delete("bucket", "key");
S3
仓库坐标
配置
think:
aws:
# aws 的授权配置
enable: true
access-key-id: 'TODO key'
secret-access-key-id: 'TODO'
s3:
# 是否启用
enable: true
# aws 地址
service-endpoint: http://10.96.112.200:8080
# 如果非外网的私有云直接使用以下地址即可,如果私有云使用反向代理,配置代理地址即可
endpoint-url: http://10.96.112.200:8080
# 区域,如果使用私有云的 s3 随意填写
region: us-east-1
bucket-name: '桶名称'
# 是否为 aws,私有云设为 false
is-aws: false
# 启动时是否检查桶是否存在
check-bucket-name-exist: true
# 是否为路径样式(true=路径风格,false=虚拟主机风格),私有云通常设为 true
path-style-access-enabled: true
# 是否禁用分块编码,默认 false
chunked-encoding-disabled: false
# 是否启用加速模式,默认 false
accelerate-mode-enabled: false
# 是否启用有效负载签名,默认 false
payload-signing-enabled: false
# 是否启用双栈模式,默认 false
dualstack-enabled: false
# 是否强制全局桶访问,默认 false
force-global-bucket-access-enabled: false
# 是否使用 ARN 解析区域,默认 false
use-arn-region-enabled: false
# 是否启用 us-east-1 区域的全局端点,默认 false
regional-us-east-1-endpoint-enabled: false
使用
上传文件
// 上传私有文件(InputStream)
String key = awsS3UploadService.upload(inputStream, "path/to", "file.txt");
// 上传私有文件(File)
String key = awsS3UploadService.upload(file, "path/to", "file.txt");
// 上传公开可读文件
String key = awsS3UploadService.upload(inputStream, "path/to", "file.txt", true);
// 上传到指定桶
String key = awsS3UploadService.upload("other-bucket", inputStream, "path/to", "file.txt");
获取文件URL
// 获取默认有效期(1小时)的URL
String url = awsS3UploadService.getUrl(key);
// 获取指定有效期的URL
String url = awsS3UploadService.getUrl(key, Duration.ofDays(7));
// 获取指定桶和有效期的URL
String url = awsS3UploadService.getUrl("other-bucket", key, Duration.ofHours(2));
下载文件
// 下载到本地路径
awsS3UploadService.download(key, "/local/path/file.txt");
// 下载到输出流
awsS3UploadService.download(key, outputStream);
获取文件元数据
Map<String, Object> headers = awsS3UploadService.getFileHeaders(key);
String contentType = awsS3UploadService.getContentType(key);
String contentLength = awsS3UploadService.getContentLength(key);
String etag = awsS3UploadService.getEtag(key);
便捷方法
// 上传文件并获取URL
String url = awsS3UploadService.uploadFile(file, "path/to", "file.txt");
String url = awsS3UploadService.uploadFile(file, "path/to", "file.txt", Duration.ofDays(7));
// 上传到临时目录并获取URL
String url = awsS3UploadService.uploadTempFile(file, "file.txt");
// 上传公开可读文件并获取URL
String url = awsS3UploadService.uploadCanReadFile(file, "path/to", "file.txt");
S3-V2
仓库坐标
配置
think:
aws:
# aws 的授权配置
enable: true
access-key-id: 'TODO key'
secret-access-key-id: 'TODO'
s3:
# 是否启用
enable: true
# aws 地址
service-endpoint: http://10.96.112.200:8080
# 如果非外网的私有云直接使用以下地址即可,如果私有云使用反向代理,配置代理地址即可
endpoint-url: http://10.96.112.200:8080
# 区域,如果使用私有云的 s3 随意填写
region: us-east-1
bucket-name: '桶名称'
# 是否为 aws,私有云设为 false
is-aws: false
# 启动时是否检查桶是否存在
check-bucket-name-exist: true
# 是否为路径样式(true=路径风格,false=虚拟主机风格),私有云通常设为 true
path-style-access-enabled: true
# 是否启用分块编码,默认 false
chunked-encoding-enabled: false
# 是否启用加速模式,默认 false
accelerate-mode-enabled: false
# 是否启用双栈模式,默认 false
dualstack-enabled: false
# 是否使用 ARN 解析区域,默认 false
use-arn-region-enabled: false
# 是否启用多区域,默认 false
multi-region-enabled: false
自动配置
自动配置类为 AwsS3V2AutoConfiguration,当 think.aws.s3.enable=true(默认为true)时自动生效。
注册的Bean
| Bean名称 | 类型 | 说明 |
|---|---|---|
|
|
S3预签名客户端,用于生成预签名URL,依赖 |
|
|
AWS S3 v2 同步客户端,依赖 |
|
|
AWS S3 v2 异步客户端,依赖 |
|
|
同步上传服务,依赖 |
|
|
异步上传服务,依赖 |
使用
同步上传服务
上传文件
// 上传私有文件(InputStream)
String key = awsS3V2UploadService.upload(inputStream, "path/to", "file.txt");
// 上传私有文件(File)
String key = awsS3V2UploadService.upload(file, "path/to", "file.txt");
// 上传公开可读文件
String key = awsS3V2UploadService.upload(inputStream, "path/to", "file.txt", true);
// 上传到指定桶
String key = awsS3V2UploadService.upload("other-bucket", inputStream, "path/to", "file.txt");
获取文件URL
// 获取默认有效期(1小时)的URL
String url = awsS3V2UploadService.getUrl(key);
// 获取指定有效期的URL
String url = awsS3V2UploadService.getUrl(key, Duration.ofDays(7));
// 获取指定桶和有效期的URL
String url = awsS3V2UploadService.getUrl("other-bucket", key, Duration.ofHours(2));
异步上传服务
异步上传文件
// 异步上传私有文件(InputStream)
CompletableFuture<String> future = awsS3V2AsyncUploadService.upload(inputStream, "path/to", "file.txt");
// 异步上传私有文件(File)
CompletableFuture<String> future = awsS3V2AsyncUploadService.upload(file, "path/to", "file.txt");
// 异步上传公开可读文件
CompletableFuture<String> future = awsS3V2AsyncUploadService.upload(inputStream, "path/to", "file.txt", true);
// 异步上传到指定桶
CompletableFuture<String> future = awsS3V2AsyncUploadService.upload("other-bucket", inputStream, "path/to", "file.txt");
异步下载文件
// 异步下载到本地路径
CompletableFuture<Void> future = awsS3V2AsyncUploadService.download(key, "/local/path/file.txt");
// 异步下载到输出流
CompletableFuture<Void> future = awsS3V2AsyncUploadService.download(key, outputStream);
异步获取文件元数据
CompletableFuture<Map<String, Object>> headersFuture = awsS3V2AsyncUploadService.getFileHeaders(key);
CompletableFuture<String> contentTypeFuture = awsS3V2AsyncUploadService.getContentType(key);
CompletableFuture<String> contentLengthFuture = awsS3V2AsyncUploadService.getContentLength(key);
CompletableFuture<String> etagFuture = awsS3V2AsyncUploadService.getEtag(key);
直接使用底层客户端
如果 UploadService / AsyncUploadService 提供的API不满足需求,可以直接注入底层客户端进行自定义操作:
// 注入同步客户端
@Autowired
private S3Client s3Client;
// 注入异步客户端
@Autowired
private S3AsyncClient s3AsyncClient;
// 注入预签名客户端
@Autowired
private S3Presigner s3Presigner;
// 也可以从UploadService获取
@Autowired
private UploadService awsS3V2UploadService;
S3Client s3Client = ((AwsS3V2UploadService) awsS3V2UploadService).getS3Client();
// 从AsyncUploadService获取
@Autowired
private AsyncUploadService awsS3V2AsyncUploadService;
S3AsyncClient s3AsyncClient = ((AwsS3V2AsyncUploadService) awsS3V2AsyncUploadService).getS3AsyncClient();
与S3 v1的区别
| 特性 | S3 (v1) | S3-V2 |
|---|---|---|
SDK版本 |
AWS SDK v1 ( |
AWS SDK v2 ( |
同步客户端 |
|
|
异步客户端 |
不支持 |
|
预签名 |
内置于 |
独立的 |
分块编码配置 |
|
|
有效负载签名 |
支持 ( |
不支持 |
全局桶访问 |
支持 ( |
不支持 |
us-east-1端点 |
支持 ( |
不支持 |
多区域 |
不支持 |
支持 ( |