将图片上传到阿里云OSS
chen subao Lv1

上传至OSS后可以减小项目大小,文件能够统一管理,也可以配置CDN加速提升用户体验。文章基于Maven构建SpringBoot项目。

引入依赖

1
2
3
4
5
<dependency>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-sdk-oss</artifactId>
<version>3.11.2</version>
</dependency>

使用配置文件

可进行环境区分,不同环境不同的OSS地址

1
2
3
4
5
6
7
8
9
10
oss:
# https://help.aliyun.com/document_detail/32010.html?spm=a2c4g.11186623.6.931.233f14a0umRAJ0
ali-yun:
endpoint:
bucket: # 文件上传至哪个bucket
bucket-domain: # 在浏览器中访问图片需要一个域名指向bucket
access-key-id:
access-key-secret:
configuration:
...

接收配置参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
import com.aliyun.oss.ClientBuilderConfiguration;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

/**
* 阿里云OSS参数配置接收
* https://help.aliyun.com/document_detail/32010.html?spm=a2c4g.11186623.6.931.1e4a14a0zzx84v
*/
@Data
@Component
@ConfigurationProperties("oss.ali-yun")
public class AliYunOssProps {

/**
* 上传节点
*/
private String endpoint;

/**
* bucket name
*/
private String bucket;

/**
* bucket对外访问的域名
*/
private String bucketDomain;

/**
* 访问key id
*/
private String accessKeyId;

/**
* 访问key secret
*/
private String accessKeySecret;

/**
* 相关的参数配置(连接超时时间,重试次数,...)
*/
private ClientBuilderConfiguration configuration;
}

全局配置OSSClient

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import com.aliyun.oss.OSSClient;
import com.aliyun.oss.OSSClientBuilder;
import com.jieyatech.config.props.AliYunOssProps;
import com.jieyatech.config.props.OssProps;
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
@RequiredArgsConstructor
public class OssConfig {

private final AliYunOssProps aliYunOssProps;

@Bean("aliYunOssClient")
public OSSClient aliYunOssClient() {
return (OSSClient) new OSSClientBuilder().build(
aliYunOssProps.getEndpoint(),
aliYunOssProps.getAccessKeyId(),
aliYunOssProps.getAccessKeySecret(),
aliYunOssProps.getConfiguration()
);
}
}

上传工具类

使用方式可以有多种多样,选择合适的就好

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
import com.aliyun.oss.ClientException;
import com.aliyun.oss.OSSClient;
import com.aliyun.oss.OSSException;
import com.aliyun.oss.model.CannedAccessControlList;
import com.aliyun.oss.model.DeleteObjectsRequest;
import com.aliyun.oss.model.OSSObject;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.StringUtils;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.List;
import java.util.Objects;
import java.util.function.Supplier;

/**
* 阿里云OSS操作帮助类
*/
@Slf4j
public class AliYunOssHelper {

private AliYunOssHelper() {}

private static final OSSClient aliYunOssClient;
private static final AliYunOssProps aliYunOssProps;

static {
aliYunOssClient = SpringContextHolder.getBean("aliYunOssClient");
aliYunOssProps = SpringContextHolder.getBean(AliYunOssProps.class);
}

/**
* 简单文件上传
* https://help.aliyun.com/document_detail/84781.html?spm=a2c4g.11186623.6.953.67113b68eB98DD
*
* @param inputStream 文件流
* @param path 对应oss中路径
* @return 简单的返回上传成功链接,视具体业务而定是否需要此链接
*/
public static String simpleUpload(InputStream inputStream, String path) {
String url;
try {
String filename = StringUtils.getFilename(path);
url = ossProps.getAliYun().getBucketDomain() + "/" + path.replace(Objects.requireNonNull(filename), "") + URLEncoder.encode(filename, "utf-8");
} catch (UnsupportedEncodingException e) {
throw new RuntimeException();
}
requestHandler(() -> aliYunOssClient.putObject(ossProps.getAliYun().getBucket(), path, inputStream));
return url;
}

/**
* 判断文件是否存在
*
* @param path 路径
* @return true|false
*/
public static boolean isExist(String path) {
return isExist(path, true);
}

/**
* 判断文件是否存在
*
* @param path 路径
* @param isOnlyInOSS 如果为true则忽略302重定向或镜像;如果为false,则考虑302重定向或镜像
* @return true|false
*/
public static boolean isExist(String path, boolean isOnlyInOSS) {
return resultHandler(() -> aliYunOssClient.doesObjectExist(ossProps.getAliYun().getBucket(), path, isOnlyInOSS));
}

/**
* 删除单个文件
*
* @param path 路径
*/
public static void deleteSingle(String path) {
requestHandler(() -> aliYunOssClient.deleteObject(ossProps.getAliYun().getBucket(), path));
}

/**
* 删除多个文件
*
* @param paths 路径集合
* @return 删除结果。详细模式下为删除成功的文件列表,简单模式下为删除失败的文件列表。
*/
public static List<String> deleteBatch(List<String> paths) {
return deleteBatch(paths, true);
}

/**
* 删除多个文件
*
* @param paths 路径集合
* @param quiet 是否详细模式
* @return 删除结果。详细模式下为删除成功的文件列表,简单模式下为删除失败的文件列表。
*/
public static List<String> deleteBatch(List<String> paths, boolean quiet) {
return resultHandler(() -> {
DeleteObjectsRequest deleteObjectsRequest = new DeleteObjectsRequest(ossProps.getAliYun().getBucket())
.withKeys(paths);
deleteObjectsRequest.setQuiet(quiet);
return aliYunOssClient.deleteObjects(deleteObjectsRequest).getDeletedObjects();
});
}

/**
* 单个路径私有访问,权限私有
*
* @param path 路径
*/
public static void filePrivateAccess(String path) {
requestHandler(() -> aliYunOssClient.setObjectAcl(ossProps.getAliYun().getBucket(), path, CannedAccessControlList.Private));
}

/**
* 获取oss中的文件
*
* @param path 文件地址
* @return {@link InputStream} 文件流
*/
public static InputStream getInputStream(String path) {
return resultHandler(() -> aliYunOssClient.getObject(ossProps.getAliYun().getBucket(), path).getObjectContent());
}

/**
* 结果请求处理
*
* @param supplier {@link VoidSupplier}
*/
private static void requestHandler(VoidSupplier supplier) {
try {
supplier.handle();
} catch (ClientException | OSSException e) {
// 异常处理
throw new RuntimeException();
}
}

/**
* 结果统一处理
*
* @param supplier {@link Supplier<T>}
* @param <T> 指定supplier的结果类型
* @return T 指定类型的结果
*/
private static <T> T resultHandler(Supplier<T> supplier) {
try {
return supplier.get();
} catch (ClientException | OSSException e) {
// 异常处理
throw new RuntimeException();
}
}

@FunctionalInterface
private interface VoidSupplier {
void handle();
}
}

回显图片

1
2
3
4
5
@GetMapping("show-file")
public ResponseEntity<?> showFile() {
InputStream inputStream = AliYunOssHelper.getInputStream("path");
return showFile(inputStream);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/**
* 回显文件
* @param inputStream 源文件流
* @param mediaType content type
* @return {@link ResponseEntity<InputStreamResource>}
*/
public static ResponseEntity<?> showFile(InputStream inputStream, MediaType mediaType) {
HttpHeaders headers = new HttpHeaders();
headers.add("Cache-Control", "no-cache, no-store, must-revalidate");
headers.add("Pragma", "no-cache");
headers.add("Expires", "0");
headers.setContentType(mediaType);
return ResponseEntity.ok()
.headers(headers)
.body(new InputStreamResource(inputStream));
}
 评论