当前位置:   article > 正文

Amazon s3 sdk for java2.x 最新api的简单使用_software.amazon.awssdk

software.amazon.awssdk

目录

创建存储桶

登录亚马逊控制台 查找服务“S3” 进入存储桶创建页面;

点击 “创建存储桶”进入创建页面;

获取密钥ID和密钥

点击右上方账户信息在下拉菜单中选择 “安全凭证”(Security credentials)进入我的安全凭证页面;

下滑找到 “访问密钥”标签  点击右侧  “创建访问密钥”按钮;

步骤一: “访问密钥最佳实践和替代方案” 选择适合自己的方案

步骤二:“设置描述标签”可不填

步骤三 “检索访问密钥“

关闭屏蔽公共访问权限

点击创建的存储桶名称进入详情页面后点击“权限”标签

找到 “屏蔽公共访问权限” 点击下方 “编辑” 按钮

取消勾选“阻止所有公开访问”然后点击下方 “保存更改” 按钮;在弹出的确认框中输入“确认”后点击“确认”按钮即可生效。

创建存储桶访问策略

点击创建的存储桶名称进入详情页面后点击“权限”标签

找到存储桶策略 -> 点击右侧“编辑”

创建如下访问策略

代码示例

        首先导入依赖

        工具类

国内使用s3的坑点: 

亚马逊中国区,必须进行ICP 备案,申请开发80或443端口,否则是不能通过网址直接访问s3内部对象的。


备注:以下操作基于您已有AWS账户;

需要获取:存储桶名称、所选区域、密钥ID和密钥;

创建存储桶

点击 “创建存储桶”进入创建页面;

  1. 输入存储桶名称 、选择区域;

        2. 其他设置保持默认即可;

        3. 点击 “创建存储桶”,即可完成存储桶的创建;

获取密钥ID和密钥

点击右上方账户信息在下拉菜单中选择 “安全凭证”(Security credentials)进入我的安全凭证页面;

下滑找到 “访问密钥”标签  点击右侧  “创建访问密钥”按钮;

  1. 进入创建访问密钥之后

步骤一: “访问密钥最佳实践和替代方案” 选择适合自己的方案

  •  勾选下方复选框
  • 点击下一步;

步骤二:“设置描述标签”可不填

  • 点击 “创建访问密钥”按钮即可创建密钥;

步骤三 “检索访问密钥“

  1. 点击“下载.csv文件“ 保存密钥ID和密钥
  2. 注意:请保存好下载的.csv文件,离开此页面后“密钥”将没有地方获取查看;

关闭屏蔽公共访问权限

点击创建的存储桶名称进入详情页面后点击“权限”标签

找到 “屏蔽公共访问权限” 点击下方 “编辑” 按钮

取消勾选“阻止所有公开访问”然后点击下方 “保存更改” 按钮;在弹出的确认框中输入“确认”后点击“确认”按钮即可生效。

创建存储桶访问策略

点击创建的存储桶名称进入详情页面后点击“权限”标签

  1. 找到存储桶策略 -> 点击右侧“编辑”

  1. 创建如下访问策略

  1. {
  2. "Version": "2012-10-17",
  3. "Id": "GetImgAndPdf",
  4. "Statement": [
  5. {
  6. "Sid": "GetImgAndPdf123",
  7. "Effect": "Allow",
  8. "Principal": {
  9. "AWS": "*"
  10. },
  11. "Action": "s3:GetObject",
  12. "Resource": "arn:aws-cn:s3:::所创建存储桶名称/*"
  13. }
  14. ]
  15. }

代码示例

        首先导入依赖

  1. <dependencyManagement>
  2. <dependencies>
  3. <!-- aws s3 -->
  4. <dependency>
  5. <groupId>software.amazon.awssdk</groupId>
  6. <artifactId>bom</artifactId>
  7. <version>${awsjavasdk.version}</version>
  8. <type>pom</type>
  9. <scope>import</scope>
  10. </dependency>
  11. </dependencies>
  12. </dependencyManagement>
  13. <dependencies>
  14. <!-- amazon s3 -->
  15. <dependency>
  16. <groupId>software.amazon.awssdk</groupId>
  17. <artifactId>s3</artifactId>
  18. </dependency>
  19. <dependency>
  20. <groupId>software.amazon.awssdk</groupId>
  21. <artifactId>kms</artifactId>
  22. </dependency>
  23. <dependency>
  24. <groupId>software.amazon.awssdk</groupId>
  25. <artifactId>s3control</artifactId>
  26. </dependency>
  27. <dependency>
  28. <groupId>software.amazon.awssdk</groupId>
  29. <artifactId>s3-transfer-manager</artifactId>
  30. </dependency>
  31. <dependency>
  32. <groupId>software.amazon.awssdk.crt</groupId>
  33. <artifactId>aws-crt</artifactId>
  34. <version>0.24.0</version>
  35. </dependency>
  36. </dependencies>

        工具类

  1. package com.trainingos.file.utils;
  2. import com.trainingos.common.util.StringUtils;
  3. import com.trainingos.common.util.file.FileTypeUtils;
  4. import lombok.extern.slf4j.Slf4j;
  5. import org.apache.commons.io.FilenameUtils;
  6. import org.apache.http.entity.ContentType;
  7. import org.springframework.mock.web.MockMultipartFile;
  8. import org.springframework.web.multipart.MultipartFile;
  9. import software.amazon.awssdk.core.sync.RequestBody;
  10. import software.amazon.awssdk.services.s3.*;
  11. import software.amazon.awssdk.services.s3.model.*;
  12. import software.amazon.awssdk.services.s3.presigner.S3Presigner;
  13. import software.amazon.awssdk.services.s3.presigner.model.GetObjectPresignRequest;
  14. import software.amazon.awssdk.services.s3.presigner.model.PresignedGetObjectRequest;
  15. import java.io.*;
  16. import java.nio.charset.Charset;
  17. import java.nio.file.Path;
  18. import java.time.Duration;
  19. import java.util.ArrayList;
  20. import java.util.List;
  21. import java.util.Objects;
  22. import java.util.zip.ZipEntry;
  23. import java.util.zip.ZipFile;
  24. import java.util.zip.ZipInputStream;
  25. /**
  26. * @Description 亚马逊文件上传工具类
  27. * @Author ajie
  28. **/
  29. @Slf4j
  30. public class FileS3Utils {
  31. /**
  32. * 密钥ID
  33. */
  34. @Value("${aws.s3.accessKeyId}")
  35. private String accessKeyId;
  36. /**
  37. * 密钥
  38. */
  39. @Value("${aws.s3.secretKey}")
  40. private String secretKey;
  41. /*@Value("${aws.s3.s3Uri}")
  42. private String s3Uri;*/
  43. /**
  44. * 存储桶名字
  45. */
  46. @Value("${aws.s3.bucket}")
  47. private String bucketName;
  48. /**
  49. * 地区节点
  50. */
  51. @Value("${aws.s3.region}")
  52. private String regionCode;
  53. /**
  54. * 资源映射前缀
  55. */
  56. @Value("${aws.s3.path}")
  57. private String filePathPrefix;
  58. public static String S3_ACCESS_KEY_ID = null;
  59. public static String S3_SECRET_KEY = null;
  60. //public static String S3_URI = null;
  61. public static String S3_BUCKET = null;
  62. public static String S3_REGION = null;
  63. public static String S3_PATH_PREFIX = null;
  64. /**
  65. * 初始化
  66. */
  67. @PostConstruct
  68. public void init() {
  69. S3_ACCESS_KEY_ID = accessKeyId;
  70. S3_SECRET_KEY = secretKey;
  71. //S3_URI = s3Uri;
  72. S3_BUCKET = bucketName;
  73. S3_REGION = regionCode;
  74. S3_PATH_PREFIX = filePathPrefix;
  75. }
  76. /**
  77. * S3客户端对象
  78. */
  79. private static S3Client s3Client;
  80. public static S3TransferManager transferManager;
  81. /**
  82. * 预签名对象
  83. */
  84. private static S3Presigner s3Presigner;
  85. /**
  86. * 获取S3客户端对象
  87. *
  88. * @return S3Client
  89. */
  90. public static synchronized S3Client getS3Client() {
  91. if (null == s3Client) {
  92. s3Client = S3Client.builder()
  93. .credentialsProvider(StaticCredentialsProvider.create(AwsBasicCredentials.create(S3_ACCESS_KEY_ID, S3_SECRET_KEY)))
  94. //.endpointConfiguration(new AwsClientBuilder.EndpointConfiguration(hostName, region)) // 如果有endpoint,可以用这个,这个和withRegion(Region)不能一起使用
  95. //.withPathStyleAccessEnabled(true) // 如果配置了S3域名,就需要加这个进行路径访问,要不然会报AccessKey不存在的问题
  96. .region(Region.of(S3_REGION))
  97. .build();
  98. }
  99. return s3Client;
  100. }
  101. /**
  102. * 上传大文件 高级API
  103. * @return
  104. */
  105. private static synchronized S3TransferManager getTransferManager(){
  106. if(null == transferManager){
  107. S3AsyncClient s3AsyncClient =
  108. S3AsyncClient.crtBuilder()
  109. .credentialsProvider(StaticCredentialsProvider.create(AwsBasicCredentials.create(S3_ACCESS_KEY_ID, S3_SECRET_KEY)))
  110. .region(Region.of(S3_REGION))
  111. //.targetThroughputInGbps(20.0)
  112. //.minimumPartSizeInBytes(8 * MB)
  113. .build();
  114. transferManager =
  115. S3TransferManager.builder()
  116. .s3Client(s3AsyncClient)
  117. .build();
  118. }
  119. return transferManager;
  120. }
  121. /**
  122. * 获取预签名对象
  123. *
  124. * @return
  125. */
  126. public static synchronized S3Presigner getS3PreSigner() {
  127. if (null == s3Presigner) {
  128. s3Presigner = S3Presigner.builder()
  129. // 凭证
  130. .credentialsProvider(StaticCredentialsProvider.create(AwsBasicCredentials.create(S3_ACCESS_KEY_ID, S3_SECRET_KEY)))
  131. //.endpointOverride(URI.create(S3_URI))
  132. // 服务配置
  133. //.serviceConfiguration(S3Configuration.builder().checksumValidationEnabled(false).pathStyleAccessEnabled(true).build())
  134. // 区域
  135. .region(Region.of(S3_REGION))
  136. .build();
  137. }
  138. return s3Presigner;
  139. }
  140. /**
  141. * 上传文件
  142. *
  143. * @param s3
  144. * @param bucketName
  145. * @param awsFilePrefix aws资源映射前缀
  146. * @param file
  147. * @param catalog
  148. * @return
  149. * @throws IOException
  150. */
  151. public static String uploadPublicFile(S3Client s3, String bucketName, String awsFilePrefix, MultipartFile file, String catalog) throws IOException {
  152. // 生成新文件名
  153. String fileName = FileUploadUtils.extractFilename(file);
  154. try {
  155. String keyName = awsFilePrefix + catalog + "/" + fileName;
  156. log.info("keyName===》 {} ", keyName);
  157. String contentType = FileTypeUtils.getFileType(fileName);
  158. log.info("文件类型===》 {} ", contentType);
  159. // 使用PutObjectRequest来设置附加的值
  160. PutObjectRequest putObjectRequest = PutObjectRequest.builder()
  161. .bucket(bucketName)
  162. .key(keyName)
  163. .contentType(contentType)
  164. .contentLength(file.getSize())
  165. .acl(ObjectCannedACL.PUBLIC_READ)
  166. .build();
  167. // 上传文件
  168. s3.putObject(putObjectRequest, RequestBody.fromBytes(file.getBytes()));
  169. log.info("======上传成功=======》 {} ", catalog + "/" + fileName);
  170. return catalog + "/" + fileName;
  171. } catch (S3Exception | IOException e) {
  172. log.info("上传文件:", e);
  173. throw new IOException(e.getMessage(), e);
  174. }
  175. }
  176. /**
  177. * 预览 有效时间为1天
  178. *
  179. * @param key 文件地址 桶中文件全路径
  180. * @return
  181. */
  182. private static String getPreSignatureUrl(S3Presigner s3Presigner, String bucketName, String key) throws Exception {
  183. String preSignatureUrl = "";
  184. try {
  185. GetObjectRequest getObjectRequest = GetObjectRequest.builder()
  186. .bucket(bucketName)
  187. .key(key)
  188. .build();
  189. //设置预签名URL可访问时间 1天
  190. GetObjectPresignRequest getObjectPresignRequest = GetObjectPresignRequest.builder()
  191. .signatureDuration(Duration.ofDays(1))
  192. .getObjectRequest(getObjectRequest)
  193. .build();
  194. PresignedGetObjectRequest presignedGetObjectRequest = s3Presigner.presignGetObject(getObjectPresignRequest);
  195. preSignatureUrl = String.valueOf(presignedGetObjectRequest.url());
  196. } catch (Exception e) {
  197. log.info("生成预签名URL失败,异常: ", e);
  198. throw new Exception(e.getMessage(), e);
  199. }
  200. return preSignatureUrl;
  201. }
  202. /**
  203. * 检查对象是否存在
  204. *
  205. * @param s3Client s3客户端
  206. * @param key 文件在桶中的全路径地址
  207. * @return
  208. */
  209. public static boolean checkIfObjectExists(S3Client s3Client, String bucketName, String key) {
  210. try {
  211. HeadObjectRequest headObjectRequest = HeadObjectRequest.builder()
  212. .bucket(bucketName)
  213. .key(key)
  214. .build();
  215. s3Client.headObject(headObjectRequest);
  216. return true; // 对象存在
  217. } catch (NoSuchKeyException e) {
  218. return false; // 对象不存在
  219. } catch (S3Exception e) {
  220. log.info("Error checking if object exists: ", e);
  221. return false; // 其他错误
  222. }
  223. }
  224. /**
  225. * 流的方式上传文件到s3桶
  226. *
  227. * @param s3Client
  228. * @param bucketName
  229. * @param key
  230. * @param file
  231. */
  232. public static void uploadFileStream(S3Client s3Client, String bucketName, String key, File file) {
  233. try {
  234. FileInputStream fileInputStream = new FileInputStream(file);
  235. PutObjectRequest objectRequest = PutObjectRequest.builder()
  236. .bucket(bucketName)
  237. .key(key)
  238. .build();
  239. // 使用 RequestBody.fromInputStream 方法将文件流上传到 S3
  240. s3Client.putObject(objectRequest, RequestBody.fromInputStream(fileInputStream, file.length()));
  241. System.out.println("File uploaded to S3 successfully.");
  242. } catch (Exception e) {
  243. System.err.println("Error uploading file to S3: " + e.getMessage());
  244. }
  245. }
  246. /**
  247. * 获取桶中某目录下所有文件
  248. *
  249. * @param s3Client
  250. * @param bucketName
  251. * @param prefix 指定前缀,例如文件夹路径
  252. * @return
  253. */
  254. public static List<S3Object> listFilesInBucket(S3Client s3Client, String bucketName, String prefix) {
  255. ListObjectsV2Request listObjectsRequest = ListObjectsV2Request.builder()
  256. .bucket(bucketName)
  257. .prefix(prefix)
  258. .build();
  259. ListObjectsV2Response response = s3Client.listObjectsV2(listObjectsRequest);
  260. return response.contents();
  261. }
  262. /**
  263. * 上传对象
  264. */
  265. // public static void main(String[] args){
  266. //
  267. // try{
  268. // Long start = System.currentTimeMillis();
  269. // String baseUrl = "upload/images/common/";
  270. //
  271. // //File file = new File("C://Users//阿杰//Pictures//微信图片_20220106110701.png");
  272. // File file = new File("C://Users//阿杰//Videos//《历史关头——红色纪念馆之旅》第二集:星星之火,可以燎原.mp4");
  273. //
  274. // boolean b = checkIfObjectExists(getS3Client(), "《历史关头——红色纪念馆之旅》第二集:星星之火,可以燎原.mp4");
  275. // if(b){
  276. // log.info("============文件已存在=====");
  277. // return;
  278. // }
  279. // //multipartUpload(baseUrl + "/《历史关头——红色纪念馆之旅》第二集:星星之火,可以燎原.mp4",file);
  280. //
  281. // //MultipartFile multipartFile = getMultipartFile(file);
  282. //
  283. // //String address = uploadPublicFile(baseUrl, multipartFile);
  284. // log.info("===========上传完成=====用时:{}",(double)(System.currentTimeMillis()-start)/1000);
  285. // //log.info("=========文件地址=====》 {} ", address);
  286. //
  287. // //String upload = FileUploadUtils.upload("D:/wenjian/project" + File.separator + "png", multipartFile);
  288. // //log.info("=========文件地址=====》 {} ", upload);
  289. //
  290. // log.info("================================================");
  291. //
  292. // //String preview = getPreSignatureUrl(baseUrl + "2023/11/06/《历史关头——红色纪念馆之旅》第二集:星星之火,可以燎原_20231106150748A001.mp4");
  293. // //log.info("=========文件预览地址=====》 {} ", preview);
  294. //
  295. // //getURL(baseUrl + "《历史关头——红色纪念馆之旅》第二集:星星之火,可以燎原.mp4");
  296. //
  297. // //===================================================
  298. // }catch (Exception e){
  299. // log.info("============",e);
  300. // }
  301. // }
  302. /**
  303. * file 转 MultipartFile
  304. *
  305. * @param file
  306. * @return
  307. */
  308. public static MultipartFile converFileToMultipartFile(File file) throws IOException {
  309. InputStream inputStream = new FileInputStream(file);
  310. return new MockMultipartFile(file.getName(), file.getName(), ContentType.APPLICATION_OCTET_STREAM.toString(), inputStream);
  311. }
  312. /**
  313. * 转换 MultipartFile 为 File 对象
  314. *
  315. * @param multipartFile
  316. * @return
  317. * @throws IOException
  318. */
  319. public static File convertMultipartFileToFile(MultipartFile multipartFile) throws IOException {
  320. File file = new File(Objects.requireNonNull(multipartFile.getOriginalFilename()));
  321. try (OutputStream os = new FileOutputStream(file)) {
  322. os.write(multipartFile.getBytes());
  323. }
  324. return file;
  325. }
  326. private static final long PART_SIZE = 100 * 1024 * 1024; // 设置文件分段大小 100 M
  327. /**
  328. * 计算分段数量
  329. */
  330. public static long getPartNumber(long fileLength) {
  331. if (fileLength % PART_SIZE == 0) {
  332. return fileLength / PART_SIZE;
  333. } else {
  334. return fileLength / PART_SIZE + 1;
  335. }
  336. }
  337. private static void multipartUpload(S3Client s3Client, String bucketName, String objectKey, File file) {
  338. CreateMultipartUploadRequest createMultipartUploadRequest = CreateMultipartUploadRequest.builder()
  339. .bucket(bucketName)
  340. .key(objectKey)
  341. .build();
  342. CreateMultipartUploadResponse response = s3Client.createMultipartUpload(createMultipartUploadRequest);
  343. String uploadId = response.uploadId();
  344. try {
  345. FileInputStream fis = new FileInputStream(file);
  346. List<CompletedPart> completedParts = new ArrayList<>();
  347. final long fileLength = file.length();
  348. final long partNumber = getPartNumber(fileLength);
  349. log.info("multipartUpload fileLength={}, partNumber={},uploadId={}", fileLength, partNumber, uploadId);
  350. for (int i = 1; i <= partNumber; i++) {
  351. final byte[] bytes = fis.readNBytes((int) PART_SIZE);
  352. //String md5 = new String(Base64.encodeBase64(DigestUtils.md5(bytes)));
  353. UploadPartRequest uploadPartRequest = UploadPartRequest.builder()
  354. .bucket(bucketName)
  355. .key(objectKey)
  356. .uploadId(uploadId)
  357. .partNumber(i)
  358. //.contentMD5(md5)
  359. .build();
  360. final RequestBody requestBody = RequestBody.fromBytes(bytes);
  361. UploadPartResponse uploadPartResponse = s3Client.uploadPart(uploadPartRequest, requestBody);
  362. String eTag = uploadPartResponse.eTag();
  363. CompletedPart part = CompletedPart.builder().partNumber(i).eTag(eTag).build();
  364. completedParts.add(part);
  365. }
  366. CompletedMultipartUpload completedMultipartUpload = CompletedMultipartUpload.builder()
  367. .parts(completedParts)
  368. .build();
  369. CompleteMultipartUploadRequest completeMultipartUploadRequest =
  370. CompleteMultipartUploadRequest.builder()
  371. .bucket(bucketName)
  372. .key(objectKey)
  373. .uploadId(uploadId)
  374. .multipartUpload(completedMultipartUpload)
  375. .build();
  376. s3Client.completeMultipartUpload(completeMultipartUploadRequest);
  377. } catch (Exception e) {
  378. log.error("S3 multipartUpload fail!", e);
  379. // 停止正在进行的分段上传,清理已上传分段
  380. s3Client.abortMultipartUpload(AbortMultipartUploadRequest.builder()
  381. .bucket(bucketName)
  382. .key(objectKey)
  383. .uploadId(uploadId)
  384. .build());
  385. }
  386. }
  387. /*public static void main(String[] args) {
  388. Long start = System.currentTimeMillis();
  389. // 设置所在的AWS Region
  390. Region region = Region.of(S3_REGION); // 根据您的需求更改Region
  391. // 创建 S3 客户端
  392. S3Client s3 = S3Client.builder().credentialsProvider(StaticCredentialsProvider.create(AwsBasicCredentials.create(S3_ACCESS_KEY_ID, S3_SECRET_KEY))).region(region).build();
  393. // 定义所使用的存储桶和文件键值
  394. String bucketName = "nxbvideo"; // 请替换为您要使用的存储桶名称
  395. String key = "《历史关头——红色纪念馆之旅》第二集:星星之火,可以燎原.mp4"; // 请替换为您要上传的文件的键值
  396. // 定义本地文件路径
  397. Path filePath = Paths.get("C://Users//阿杰//Videos//《历史关头——红色纪念馆之旅》第二集:星星之火,可以燎原.mp4"); // 请替换为您要上传的本地文件路径
  398. // 开始分段上传
  399. String uploadId = initiateMultipartUpload(s3, bucketName, key);
  400. // 选择每个分段的大小(100MB),可以根据需要调整分段大小
  401. long partSize = 100 * 1024 * 1024;
  402. // 分割文件并上传每个部分
  403. List<CompletedPart> completedParts = uploadParts(s3, bucketName, key, filePath, partSize,uploadId);
  404. System.out.println("completedParts 分了==========>"+completedParts.size());
  405. // 完成分段上传
  406. completeMultipartUpload(s3, bucketName, key, uploadId, completedParts);
  407. log.info("===========上传完成=====用时:{}",(double)(System.currentTimeMillis()-start)/1000);
  408. // 关闭 S3 客户端
  409. s3.close();
  410. }*/
  411. // 初始化分段上传
  412. public static String initiateMultipartUpload(S3Client s3, String bucketName, String key) {
  413. CreateMultipartUploadResponse response = s3.createMultipartUpload(
  414. CreateMultipartUploadRequest.builder()
  415. .bucket(bucketName)
  416. .key(key)
  417. .build()
  418. );
  419. return response.uploadId();
  420. }
  421. // 分割文件并上传每个部分
  422. public static List<CompletedPart> uploadParts(S3Client s3, String bucketName, String key, Path filePath, long partSize, String uploadId) {
  423. List<CompletedPart> completedParts = new ArrayList<>();
  424. try {
  425. long filePosition = 0;
  426. long contentLength = filePath.toFile().length();
  427. for (int partNumber = 1; filePosition < contentLength; partNumber++) {
  428. long remainingBytes = contentLength - filePosition;
  429. long byteCount = Math.min(partSize, remainingBytes);
  430. UploadPartRequest uploadPartRequest = UploadPartRequest.builder()
  431. .bucket(bucketName)
  432. .key(key)
  433. .uploadId(uploadId)
  434. .partNumber(partNumber)
  435. .contentLength(byteCount)
  436. .build();
  437. UploadPartResponse response = s3.uploadPart(
  438. uploadPartRequest,
  439. RequestBody.fromFile(filePath)
  440. );
  441. completedParts.add(CompletedPart.builder()
  442. .partNumber(partNumber)
  443. .eTag(response.eTag())
  444. .build());
  445. filePosition += byteCount;
  446. }
  447. return completedParts;
  448. } catch (Exception e) {
  449. System.err.println("Multipart upload failed: " + e.getMessage());
  450. s3.abortMultipartUpload(AbortMultipartUploadRequest.builder()
  451. .bucket(bucketName)
  452. .key(key)
  453. .uploadId(uploadId)
  454. .build());
  455. return null;
  456. }
  457. }
  458. // 中止分段上传
  459. public static void abortMultipartUpload(S3Client s3, String bucketName, String key, String uploadId) {
  460. s3.abortMultipartUpload(AbortMultipartUploadRequest.builder()
  461. .bucket(bucketName)
  462. .key(key)
  463. .uploadId(uploadId)
  464. .build());
  465. System.out.println("Multipart upload aborted.");
  466. }
  467. // 续传分段
  468. public static void resumeMultipartUpload(S3Client s3, String bucketName, String key, Path filePath, long partSize, String uploadId, List<CompletedPart> completedParts) {
  469. // 重新初始化分段上传
  470. uploadId = initiateMultipartUpload(s3, bucketName, key);
  471. // 检查哪些分段已经上传
  472. long partNumber = completedParts.size() + 1;
  473. long filePosition = completedParts.stream()
  474. .mapToLong(part -> part.partNumber())
  475. .sum() * partSize;
  476. try {
  477. long contentLength = filePath.toFile().length();
  478. for (; filePosition < contentLength; partNumber++) {
  479. long remainingBytes = contentLength - filePosition;
  480. long byteCount = Math.min(partSize, remainingBytes);
  481. UploadPartResponse response = s3.uploadPart(
  482. UploadPartRequest.builder()
  483. .bucket(bucketName)
  484. .key(key)
  485. .uploadId(uploadId)
  486. .partNumber((int) partNumber)
  487. .contentLength(byteCount)
  488. .build(),
  489. RequestBody.fromFile(filePath)
  490. );
  491. completedParts.add(CompletedPart.builder()
  492. .partNumber((int) partNumber)
  493. .eTag(response.eTag())
  494. .build());
  495. filePosition += byteCount;
  496. }
  497. // 完成续传的分段上传
  498. completeMultipartUpload(s3, bucketName, key, uploadId, completedParts);
  499. } catch (Exception e) {
  500. System.err.println("Multipart upload failed: " + e.getMessage());
  501. abortMultipartUpload(s3, bucketName, key, uploadId);
  502. }
  503. }
  504. // 完成分段上传
  505. public static void completeMultipartUpload(S3Client s3, String bucketName, String key, String uploadId, List<CompletedPart> completedParts) {
  506. CompleteMultipartUploadResponse response = s3.completeMultipartUpload(
  507. CompleteMultipartUploadRequest.builder()
  508. .bucket(bucketName)
  509. .key(key)
  510. .uploadId(uploadId)
  511. .multipartUpload(CompletedMultipartUpload.builder().parts(completedParts).build())
  512. .build()
  513. );
  514. System.out.println("Multipart upload completed. ETag: " + response.eTag());
  515. // 因为在分段上传过程中,单独的每个分段并不包含文件的完整 Metadata。
  516. // 在完成上传之后,使用 CopyObjectRequest 设置文件类型
  517. // 创建 Metadata 对象并设置文件类型
  518. /*Map<String, String> metadata = new HashMap<>();
  519. metadata.put("Content-Type", "application/zip");
  520. CopyObjectRequest copyObjectRequest = CopyObjectRequest.builder()
  521. .copySource(bucketName + "/" + key)
  522. .destinationBucket(bucketName)
  523. .destinationKey(key)
  524. .metadataDirective(MetadataDirective.REPLACE) // 覆盖现有元数据
  525. .metadata(metadata)
  526. .build();
  527. s3.copyObject(copyObjectRequest);
  528. System.out.println("Multipart upload completed. Content-Type set to application/zip.");*/
  529. }
  530. // 分片上传
  531. /*public static void main(String[] args) {
  532. String bucketName = S3_BUCKET;
  533. String key = "upload/images/common/《历史关头——红色纪念馆之旅》第二集:星星之火,可以燎原.mp4"; // 文件在 S3 中的键
  534. String filePathString = "C://Users//阿杰//Videos//《历史关头——红色纪念馆之旅》第二集:星星之火,可以燎原.mp4"; // 本地文件路径
  535. // 创建 S3 客户端
  536. S3Client s3 = S3Client.builder()
  537. .region(Region.of(S3_REGION)) // 设置您的 S3 存储桶所在的区域
  538. .credentialsProvider(StaticCredentialsProvider.create(AwsBasicCredentials.create(S3_ACCESS_KEY_ID, S3_SECRET_KEY)))
  539. .build();
  540. // 指定要上传的本地文件路径
  541. Path filePath = Path.of(filePathString);
  542. // 设置分段大小
  543. final long PART_SIZE = 50 * 1024 * 1024; // 每个分段的大小为 50MB
  544. // 创建 InitiateMultipartUploadRequest 请求
  545. CreateMultipartUploadRequest createRequest = CreateMultipartUploadRequest.builder()
  546. .bucket(bucketName)
  547. .key(key)
  548. .build();
  549. // 初始化分段上传
  550. CreateMultipartUploadResponse createResponse = s3.createMultipartUpload(createRequest);
  551. // 获取文件大小
  552. long contentLength = filePath.toFile().length();
  553. // 计算分段数量
  554. long partCount = (contentLength + PART_SIZE - 1) / PART_SIZE;
  555. // 创建一个线程池
  556. ExecutorService executorService = Executors.newFixedThreadPool(10);
  557. try {
  558. List<Future<CompletedPart>> futures = new ArrayList<>();
  559. // 逐个上传文件的分段
  560. for (int i = 1; i <= partCount; i++) {
  561. long filePosition = (i - 1) * PART_SIZE;
  562. long partSize = Math.min(PART_SIZE, contentLength - filePosition);
  563. // 开启线程上传分段
  564. int finalI = i;
  565. Future<CompletedPart> future = executorService.submit(() -> {
  566. UploadPartRequest uploadRequest = UploadPartRequest.builder()
  567. .bucket(bucketName)
  568. .key(key)
  569. .uploadId(createResponse.uploadId())
  570. .partNumber(finalI)
  571. .build();
  572. // 读取文件分段内容
  573. RequestBody requestBody = RequestBody.fromFile(filePath);
  574. // 上传分段
  575. UploadPartResponse uploadPartResponse = s3.uploadPart(uploadRequest, requestBody);
  576. return CompletedPart.builder()
  577. .partNumber(finalI)
  578. .eTag(uploadPartResponse.eTag())
  579. .build();
  580. });
  581. futures.add(future);
  582. }
  583. List<CompletedPart> completedParts = new ArrayList<>();
  584. for (Future<CompletedPart> future : futures) {
  585. completedParts.add(future.get());
  586. }
  587. // 完成分段上传
  588. CompleteMultipartUploadRequest completeRequest = CompleteMultipartUploadRequest.builder()
  589. .bucket(bucketName)
  590. .key(key)
  591. .uploadId(createResponse.uploadId())
  592. .multipartUpload(CompletedMultipartUpload.builder()
  593. .parts(completedParts)
  594. .build())
  595. .build();
  596. s3.completeMultipartUpload(completeRequest);
  597. System.out.println("Multipart upload completed.");
  598. } catch (Exception e) {
  599. e.printStackTrace();
  600. } finally {
  601. // 关闭 S3 客户端和线程池
  602. s3.close();
  603. executorService.shutdown();
  604. }
  605. }*/
  606. // 上传大文件
  607. /*public static String uploadFile(S3TransferManager transferManager, String bucketName,
  608. String baseDir, MultipartFile file, String catalog){
  609. // 生成新文件名
  610. String fileName = FileUploadUtils.extractFilename(file);
  611. String keyName = baseDir + catalog + "/" + fileName;
  612. log.info("生成的文件路径===》 {} ", keyName);
  613. try{
  614. UploadFileRequest uploadFileRequest =
  615. UploadFileRequest.builder()
  616. .putObjectRequest(b -> b.bucket(bucketName).key(keyName))
  617. .addTransferListener(LoggingTransferListener.create())
  618. //.source(file.)
  619. .build();
  620. FileUpload fileUpload = transferManager.uploadFile(uploadFileRequest);
  621. CompletedFileUpload uploadResult = fileUpload.completionFuture().join();
  622. String s = uploadResult.response().eTag();
  623. return s;
  624. }catch (Exception e){
  625. log.info("======",e);
  626. }
  627. return "";
  628. }*/
  629. /**
  630. * 上传大文件
  631. * @param transferManager
  632. * @param bucketName
  633. * @param key
  634. * @param filePath
  635. * @return
  636. */
  637. /*public String uploadFile(S3TransferManager transferManager, String bucketName,
  638. String key, String filePath) {
  639. UploadFileRequest uploadFileRequest =
  640. UploadFileRequest.builder()
  641. .putObjectRequest(b -> b.bucket(bucketName).key(key))
  642. .addTransferListener(LoggingTransferListener.create())
  643. .source(Paths.get(filePath))
  644. .build();
  645. FileUpload fileUpload = transferManager.uploadFile(uploadFileRequest);
  646. CompletedFileUpload uploadResult = fileUpload.completionFuture().join();
  647. return uploadResult.response().eTag();
  648. }*/
  649. }

国内使用s3的坑点: 

亚马逊中国区,必须进行ICP 备案,申请开发80或443端口,否则是不能通过网址直接访问s3内部对象的。
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/菜鸟追梦旅行/article/detail/285740
推荐阅读
  

闽ICP备14008679号