amazonS3文件操作知識點匯總


1.文件上傳時,對於不存在路徑會是啥結果?
如果上傳的存儲桶不存在,會報錯。如果是存儲桶下面的文件夾不存在,則會創建一個並保存進去你上傳的文件。第二次上傳同樣的路徑,應為已經存在,則直接保存。如果上傳的路徑的 一級目錄 前面多了斜杠“/”,也會報錯。舉個例子:
指定的文件上傳的key為:/temp/20200723/小小的船-2129566950.pptx,則就會報錯。

The specified key does not exist. (Service: Amazon S3; Status Code: 404; Error Code: NoSuchKey; Request ID: DE8C45718259ACD7;
1


2.amazonS3能夠實現文件操作
上傳,下載,復制,刪除,但是沒有直接的移動操作。並且通過在進入amazonS3進行配置生命周期的規則支持后,就可以實現對上傳文件的過期時間的設置。這個過期時間的實現必須的前提條件就是要開啟對存儲桶指定目錄的生命周期。如下圖是對temp目錄設置好的生命周期規則。其中前面這個transient_rule即是ruleId。

 

3.剩下一些工具類的實現
package com.util;

import com.amazonaws.auth.AWSStaticCredentialsProvider;
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.regions.Regions;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
import com.amazonaws.services.s3.model.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.io.Resource;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestTemplate;
import software.amazon.awssdk.auth.credentials.AwsBasicCredentials;
import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.s3.S3Client;
import software.amazon.awssdk.services.s3.model.Delete;
import software.amazon.awssdk.services.s3.model.DeleteObjectsResponse;
import software.amazon.awssdk.services.s3.model.ObjectIdentifier;
import software.amazon.awssdk.services.s3.model.S3Exception;
import software.amazon.awssdk.services.s3.paginators.ListObjectsV2Iterable;

import java.io.*;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;

/**
* AmazonS3文件操作工具類
*
* @author zhanglifeng
* @date 2020-07-01
*/
public class AmazonS3Util {
private static final Logger LOGGER = LoggerFactory.getLogger(AmazonS3Util.class);
/**
* access_key_id 你的亞馬遜S3服務器訪問密鑰ID
*/
private static final String ACCESS_KEY = "AIEKIAF3TXCLQT6M7A7L";
/**
* secret_key 你的亞馬遜S3服務器訪問密鑰
*/
private static final String SECRET_KEY = "3wyLbaxZ62XnMMz517IB36c63jeRev6e8HhxemSS";
/**
* end_point 你的亞馬遜S3服務器連接路徑和端口(新版本不再需要這個,直接在創建S3對象的時候根據桶名和Region自動獲取)
*
* 格式: https://桶名.s3-你的Region名稱.amazonaws.com
* 示例: https://xxton.s3-cn-north-1.amazonaws.com
*/
//private static final String END_POINT = "https://xxton.s3-cn-north-1.amazonaws.com";
/**
* bucketname 你的亞馬遜S3服務器創建的桶名
*/
private static final String S3_BUCKET_NAME = "media.fenglizhang.com";

/**
* 創建訪問憑證對象
*/
private static final BasicAWSCredentials awsCreds = new BasicAWSCredentials(ACCESS_KEY, SECRET_KEY);
/**
* 創建s3對象
*/
private static final AmazonS3 s3Client = AmazonS3ClientBuilder.standard()
.withCredentials(new AWSStaticCredentialsProvider(awsCreds))
//設置服務器所屬地區
.withRegion(Regions.US_WEST_1)
.build();

/**
* 經過測試,文件上傳的方法這個要比下面的uploadToS3的快。
*
* @param key 文件在bucket中的存儲文件名
* @param env 當前項目的環境:dev,test,stage,prod
* @param filePath 待上傳的文件存放位置
* @param s3CdnBaseUrl cdn在不同環境的url
* @return
*/
public static String uploadToS3Fast(String key, String env, String filePath, String s3CdnBaseUrl) {
long startTime = System.currentTimeMillis();
S3Client client = S3Client.builder().region(Region.US_WEST_1).credentialsProvider(StaticCredentialsProvider.create(AwsBasicCredentials.create(ACCESS_KEY, SECRET_KEY))).build();
String bucketName = getS3BucketName(env);
software.amazon.awssdk.services.s3.model.PutObjectRequest putObjectRequest = software.amazon.awssdk.services.s3.model.PutObjectRequest.builder().bucket(bucketName).key(key).build();
client.putObject(putObjectRequest, Path.of(filePath));
String downloadUrl = String.format("https://%s/%s", s3CdnBaseUrl, key);
long endTime = System.currentTimeMillis();
LOGGER.info("上傳到S3耗時:{}", endTime - startTime);
return downloadUrl;
}


/**
* @param key 文件在bucket中的存儲文件名
* @param env 當前項目的環境:dev,test,stage,prod
* @param filePath 待上傳的文件存放位置
* @param s3CdnBaseUrl cdn在不同環境的url
* @return
*/
public static String uploadToS3(String key, String env, String filePath, String s3CdnBaseUrl) {
long startTime = System.currentTimeMillis();
String bucketName = getS3BucketName(env);
PutObjectRequest request = new PutObjectRequest(bucketName, key, new File(filePath));
s3Client.putObject(request);
String downloadUrl = String.format("https://%s/%s", s3CdnBaseUrl, key);
long endTime = System.currentTimeMillis();
LOGGER.info("上傳到S3耗時:{}", endTime - startTime);
return downloadUrl;
}


/**
* @param key 文件在存儲桶中的目錄
* @param env 當前項目的環境:dev,test,stage,prod
* @param targetFilePath 緩存到本地的文件名
*/
public static void amazonS3Download(String key, String env, String targetFilePath) {
long startTime = System.currentTimeMillis();

String bucketName = getS3BucketName(env);
S3Object object = s3Client.getObject(new GetObjectRequest(bucketName, key));
if (object != null) {
LOGGER.info("Content-Type: " + object.getObjectMetadata().getContentType());
InputStream input = null;
FileOutputStream fileOutputStream = null;
byte[] data = null;
try {
//獲取文件流
input = object.getObjectContent();
data = new byte[input.available()];
int len = 0;
fileOutputStream = new FileOutputStream(targetFilePath);
while ((len = input.read(data)) != -1) {
fileOutputStream.write(data, 0, len);
}
LOGGER.info("下載文件成功");
} catch (IOException e) {
LOGGER.error("文件流轉換發生異常:{}", e);
} finally {
try {
if (fileOutputStream != null) {
fileOutputStream.flush();
fileOutputStream.close();
}
if (input != null) {
input.close();
}
long endTime = System.currentTimeMillis();
LOGGER.info("amazonS3Download方法從S3上下載文件耗時:{}", endTime - startTime);
} catch (IOException e) {
LOGGER.error("關閉文件流發生異常:{}", e);
}
}
}
}


private static String getS3BucketName(String env) {
String bucketName;
if ("prod".equals(env)) {
bucketName = S3_BUCKET_NAME;
} else if ("dev".equals(env)) {
bucketName = String.format("%s.%s", env, S3_BUCKET_NAME);
} else {
bucketName = String.format("%s.%s", "stage", S3_BUCKET_NAME);
}
return bucketName;
}

/**
* @param url 能夠通過瀏覽器打開的資源鏈接。比如:https://cdn.fenglizhang.com/cw/1495159251-0000.png
* @param saveFile 要保存的文件地址
* @param restTemplate 需要注入實例的rest客戶端
*/
public static void downloadFileFromS3(String url, File saveFile, RestTemplate restTemplate) {
try {
HttpHeaders headers = new HttpHeaders();
HttpEntity<Resource> httpEntity = new HttpEntity<>(headers);
ResponseEntity<byte[]> response = restTemplate.exchange(url, HttpMethod.GET, httpEntity, byte[].class);
FileOutputStream fos = new FileOutputStream(saveFile);
fos.write(response.getBody());
fos.flush();
fos.close();
} catch (Exception e) {
LOGGER.error(String.format("downloadFile url {} exception", url), e);
}
}

/**
* 本復制文件的方法適用於在同一個bucket中
*
* @param sourceKey Source object key
* @param env 當前應用的環境
* @param destinationKey Destination object key
*/
public static String copyObjectFromS3ToS3(String sourceKey, String env, String destinationKey, String s3CdnBaseUrl) {
String bucketName = getS3BucketName(env);
// Copy the object into a new object in the same bucket.
CopyObjectRequest copyObjRequest = new CopyObjectRequest(bucketName, sourceKey, bucketName, destinationKey);
/* ObjectMetadata objectMetadata = new ObjectMetadata();
objectMetadata.setExpirationTime();
objectMetadata.setExpirationTimeRuleId();
copyObjRequest.setNewObjectMetadata(objectMetadata);*/
CopyObjectResult copyObjectResult = s3Client.copyObject(copyObjRequest);
return String.format("https://%s/%s", s3CdnBaseUrl, destinationKey);
}

/**
* 上傳文件到暫存區並且設置文件的過期時間
* @param key 文件在bucket中的存儲文件名
* @param env 當前項目的環境:dev,test,stage,prod
* @param filePath 待上傳的文件存放位置
* @param s3CdnBaseUrl cdn在不同環境的url
* @return
*/
public static String uploadToS3TransientAndSetExpiredTime(String key, String env, String filePath, String s3CdnBaseUrl) {
long startTime = System.currentTimeMillis();
String bucketName = getS3BucketName(env);
File file = new File(filePath);
PutObjectRequest request = new PutObjectRequest(bucketName, key, file);
String downloadUrl = null;
int index = filePath.lastIndexOf(".");
String contentType = String.format("%s/%s", "application", filePath.substring(index + 1));
InputStream inputStream = null;
try {
inputStream = new FileInputStream(file);

ObjectMetadata objectMetadata = new ObjectMetadata();
// 必須設置ContentLength
objectMetadata.setContentLength(file.length());
objectMetadata.setExpirationTimeRuleId("transient_rule");
objectMetadata.setContentType(contentType);
request.setMetadata(objectMetadata);

s3Client.putObject(bucketName, key, inputStream, objectMetadata);
downloadUrl = String.format("https://%s/%s", s3CdnBaseUrl, key);
long endTime = System.currentTimeMillis();
LOGGER.info("上傳到S3耗時:{}", endTime - startTime);

} catch (FileNotFoundException e) {
LOGGER.error(e.getMessage());
} finally {
try {
inputStream.close();
} catch (IOException e) {
LOGGER.error("inputStream關閉異常,異常信息:{}",e.getMessage());
}
}
return downloadUrl;
}


/**
* 遍歷存儲桶指定文件夾下的所有文件路徑
*
* @param s3
* @param bucket
* @param prefix
* @return
*/
public static List<String> listKeysInDirectory(S3Client s3, String bucket, String prefix) {
String delimiter = "/";
if (!prefix.endsWith(delimiter)) {
prefix += delimiter;
}
// Build the list objects request
software.amazon.awssdk.services.s3.model.ListObjectsV2Request listReq = software.amazon.awssdk.services.s3.model.ListObjectsV2Request.builder()
.bucket(bucket)
.prefix(prefix)
.delimiter(delimiter)
.maxKeys(1)
.build();

ListObjectsV2Iterable listRes = s3.listObjectsV2Paginator(listReq);
List<String> keyList = new ArrayList<>();
final String folder = prefix;
listRes.contents().stream()
.forEach(content -> {
if (!folder.equals(content.key())) {
keyList.add(content.key());
}
});
return keyList;
}

/**
* 刪除指定目錄下的所有文件
*
* @param env 環境
* @param folderPath
*/
public static void deleteS3Folder(String env, String folderPath) {
String bucketName = getS3BucketName(env);
S3Client s3 = S3Client.builder().
region(Region.US_WEST_1).
credentialsProvider(StaticCredentialsProvider.create(AwsBasicCredentials.create(ACCESS_KEY, SECRET_KEY)))
.build();
ArrayList<ObjectIdentifier> to_delete = new ArrayList<ObjectIdentifier>();
List<String> object_keys = listKeysInDirectory(s3, bucketName, folderPath);
if (null == object_keys || object_keys.size() == 0) {
return;
}
for (String k : object_keys) {
to_delete.add(ObjectIdentifier.builder().key(k).build());
}
try {
software.amazon.awssdk.services.s3.model.DeleteObjectsRequest dor = software.amazon.awssdk.services.s3.model.DeleteObjectsRequest.builder()
.bucket(bucketName)
.delete(Delete.builder().objects(to_delete).build())
.build();
DeleteObjectsResponse response = s3.deleteObjects(dor);
while (!response.sdkHttpResponse().isSuccessful()) {
Thread.sleep(100);
}
} catch (S3Exception | InterruptedException e) {
LOGGER.error(e.getMessage());
}
LOGGER.info("delete folder successfully--->" + folderPath);
}
}

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
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
4.amazon上面工具類的依賴
<!-- aws依賴 -->
<dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>s3</artifactId>
<version>2.10.4</version>
<exclusions>
<exclusion>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>ses</artifactId>
<version>2.10.4</version>
<exclusions>
<exclusion>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-java-sdk-s3</artifactId>
<version>1.11.233</version>
</dependency>
————————————————
版權聲明:本文為CSDN博主「萬米高空」的原創文章,遵循CC 4.0 BY-SA版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/zhanglf02/article/details/107559433


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM