S3FileService.java 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607
  1. package com.fdkankan.fyun.s3;
  2. import cn.hutool.core.collection.CollUtil;
  3. import com.amazonaws.ClientConfiguration;
  4. import com.amazonaws.HttpMethod;
  5. import com.amazonaws.auth.AWSStaticCredentialsProvider;
  6. import com.amazonaws.auth.BasicAWSCredentials;
  7. import com.amazonaws.client.builder.AwsClientBuilder;
  8. import com.amazonaws.regions.Regions;
  9. import com.amazonaws.services.s3.AmazonS3;
  10. import com.amazonaws.services.s3.AmazonS3ClientBuilder;
  11. import com.amazonaws.services.s3.model.*;
  12. import com.fdkankan.fyun.constant.FYunTypeEnum;
  13. import com.fdkankan.fyun.face.AbstractFYunFileService;
  14. import com.fdkankan.fyun.util.FileInfoVo;
  15. import com.fdkankan.fyun.util.MD5Checksum;
  16. import org.apache.commons.lang3.StringUtils;
  17. import org.slf4j.Logger;
  18. import org.slf4j.LoggerFactory;
  19. import org.springframework.beans.factory.annotation.Autowired;
  20. import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
  21. import org.springframework.stereotype.Component;
  22. import org.springframework.util.ObjectUtils;
  23. import java.io.*;
  24. import java.math.BigDecimal;
  25. import java.net.URL;
  26. import java.util.*;
  27. import java.util.stream.Collectors;
  28. @Component
  29. @ConditionalOnProperty(name = "fyun.type",havingValue = "aws")
  30. public class S3FileService extends AbstractFYunFileService {
  31. private Logger log = LoggerFactory.getLogger(this.getClass().getName());
  32. public static AmazonS3 amazonS3(){
  33. BasicAWSCredentials awsCreds = new BasicAWSCredentials("AKIAWCV5QFZ3ZNELKYUY", "epS5ghyR4LJ7rxk/qJO9ZYh6m9Oz6g5haKDu4yws");
  34. ClientConfiguration clientConfiguration = new ClientConfiguration();
  35. clientConfiguration.setMaxErrorRetry(4);
  36. clientConfiguration.setMaxConnections(100);
  37. AwsClientBuilder.EndpointConfiguration endpointConfiguration = new AwsClientBuilder.EndpointConfiguration("test-4dkankan.s3.eu-west-2.amazonaws.com",Regions.EU_WEST_2.getName());
  38. return AmazonS3ClientBuilder.standard()
  39. .withCredentials(new AWSStaticCredentialsProvider(awsCreds))
  40. .withEndpointConfiguration(endpointConfiguration)
  41. .withClientConfiguration(clientConfiguration)
  42. // .withRegion(Regions.EU_WEST_2).
  43. .build();
  44. }
  45. @Autowired
  46. private AmazonS3 s3;
  47. @Override
  48. public String uploadFile(String bucket, byte[] data, String remoteFilePath){
  49. try {
  50. ObjectMetadata metadata = new ObjectMetadata();
  51. PutObjectRequest request = new PutObjectRequest(bucket, remoteFilePath, new ByteArrayInputStream(data), metadata);
  52. request.withCannedAcl(CannedAccessControlList.PublicRead);
  53. s3.putObject(request);
  54. } catch (Exception e) {
  55. log.error("s3上传文件失败", e);
  56. }
  57. return null;
  58. }
  59. @Override
  60. public String uploadFile(String bucket, String filePath, String remoteFilePath){
  61. return uploadFile(bucket, filePath, remoteFilePath,null);
  62. }
  63. @Override
  64. public String uploadFile(String bucket, InputStream inputStream, String remoteFilePath) {
  65. try {
  66. s3.putObject(bucket, remoteFilePath, inputStream, null);
  67. } catch (Exception e) {
  68. log.error("文件流上传失败,目标路径:{}", remoteFilePath);
  69. e.printStackTrace();
  70. }
  71. return null;
  72. }
  73. @Override
  74. public String uploadFile(String bucket, String filePath, String remoteFilePath,Map<String, String> headers){
  75. try {
  76. File file = new File(filePath);
  77. if (!file.exists()) {
  78. log.error("要上传的文件不存在:" + filePath);
  79. return null;
  80. }
  81. // 设置文件并设置公读
  82. ObjectMetadata metadata = new ObjectMetadata();
  83. if (filePath.contains(".jpg")) {
  84. metadata.setContentType("image/jpeg");
  85. }
  86. if (filePath.contains(".png")) {
  87. metadata.setContentType("image/png");
  88. }
  89. if(org.apache.commons.lang3.ObjectUtils.isNotEmpty(headers)){
  90. for (Map.Entry<String, String> header : headers.entrySet()) {
  91. metadata.setHeader(header.getKey(),header.getValue());
  92. }
  93. }
  94. PutObjectRequest request = new PutObjectRequest(bucket, remoteFilePath, file);
  95. request.withCannedAcl(CannedAccessControlList.PublicRead);
  96. request.withMetadata(metadata);
  97. // 上传文件
  98. PutObjectResult putObjectResult = s3.putObject(request);
  99. if (StringUtils.isNotEmpty(putObjectResult.getETag())) {
  100. log.info("s3上传文件成功:" + remoteFilePath);
  101. }
  102. } catch (Exception e) {
  103. log.error("文件上传失败:{}",filePath);
  104. e.printStackTrace();
  105. }
  106. return null;
  107. }
  108. @Override
  109. public String uploadFileByCommand(String bucket, String filePath, String remoteFilePath){
  110. try {
  111. String optType = new File(filePath).isDirectory() ? "folder" : "file";
  112. String command = String.format(fYunConstants.UPLOAD_SH, bucket, filePath, remoteFilePath, FYunTypeEnum.AWS.code(), optType);
  113. log.info("开始上传文件, ossPath:{}, srcPath:{}", remoteFilePath, filePath);
  114. callshell(command);
  115. } catch (Exception e) {
  116. log.error("上传文件失败, ossPath:{}, srcPath:{}", remoteFilePath, filePath);
  117. e.printStackTrace();
  118. }
  119. return null;
  120. }
  121. @Override
  122. public void copyFileBetweenBucketParallel(String sourceBucketName, String sourcePath, String targetBucketName, String targetPath) {
  123. try {
  124. List<String> files = listRemoteFiles(sourceBucketName, sourcePath);
  125. if (ObjectUtils.isEmpty(files)) {
  126. return;
  127. }
  128. files.parallelStream().forEach(file -> {
  129. CopyObjectRequest request = new CopyObjectRequest(sourceBucketName, file, targetBucketName, file.replace(sourcePath, targetPath));
  130. request.withCannedAccessControlList(CannedAccessControlList.PublicRead);
  131. s3.copyObject(request);
  132. });
  133. } catch (Exception e) {
  134. log.error("列举文件目录失败,key=" + sourcePath);
  135. }
  136. }
  137. @Override
  138. public void downloadFileByCommand(String bucket, String filePath, String remoteFilePath) {
  139. try {
  140. String optType = remoteFilePath.contains(".") ? "file" : "folder";
  141. String command = String.format(fYunConstants.DOWNLOAD_SH, bucket, remoteFilePath, filePath, FYunTypeEnum.AWS.code(), optType);
  142. log.info("开始下载文件, ossPath:{}, srcPath:{}", remoteFilePath, filePath);
  143. callshell(command);
  144. } catch (Exception e) {
  145. log.error("上传文件失败, ossPath:{}, srcPath:{}", remoteFilePath, filePath);
  146. e.printStackTrace();
  147. }
  148. }
  149. @Override
  150. public void downloadByCommand(String bucket, String filePath, String remoteFilePath, boolean isDir) {
  151. try {
  152. String optType = isDir ? "folder" : "file";
  153. String command = String.format(fYunConstants.DOWNLOAD_SH, bucket, remoteFilePath, filePath, FYunTypeEnum.AWS.code(), optType);
  154. log.info("开始下载文件, ossPath:{}, srcPath:{}", remoteFilePath, filePath);
  155. callshell(command);
  156. } catch (Exception e) {
  157. log.error("上传文件失败, ossPath:{}, srcPath:{}", remoteFilePath, filePath);
  158. e.printStackTrace();
  159. }
  160. }
  161. @Override
  162. public void deleteFile(String bucket, String remoteFilePath){
  163. if (remoteFilePath.startsWith("/")) {
  164. remoteFilePath = remoteFilePath.substring(1);
  165. }
  166. try {
  167. s3.deleteObject(bucket, remoteFilePath);
  168. } catch (Exception e) {
  169. log.error("s3删除文件失败,key=" + remoteFilePath, e);
  170. }
  171. }
  172. @Override
  173. public void deleteFolder(String bucket, String remoteFolderPath){
  174. try {
  175. if (!remoteFolderPath.endsWith("/")) {
  176. remoteFolderPath = remoteFolderPath + "/";
  177. }
  178. log.info("开始删除文件夹:{}", remoteFolderPath);
  179. int maxKeys = 1000;
  180. String nextMaker = null;
  181. ListObjectsRequest listObjectsRequest = new ListObjectsRequest();
  182. listObjectsRequest.setBucketName(bucket);
  183. listObjectsRequest.setPrefix(remoteFolderPath);
  184. listObjectsRequest.setMaxKeys(maxKeys);
  185. ObjectListing objectListing;
  186. DeleteObjectsRequest multiObjectDeleteRequest = new DeleteObjectsRequest(bucket).withQuiet(false);
  187. do {
  188. listObjectsRequest.setMarker(nextMaker);
  189. objectListing = s3.listObjects(listObjectsRequest);
  190. List<S3ObjectSummary> objectSummaries = objectListing.getObjectSummaries();
  191. List<DeleteObjectsRequest.KeyVersion> keys = objectSummaries.stream().map(summary -> new DeleteObjectsRequest.KeyVersion(summary.getKey())).collect(Collectors.toList());
  192. if (!ObjectUtils.isEmpty(keys)) {
  193. multiObjectDeleteRequest.setKeys(keys);
  194. s3.deleteObjects(multiObjectDeleteRequest);
  195. }
  196. nextMaker = objectListing.getNextMarker();
  197. } while (objectListing.isTruncated());
  198. } catch (Exception e) {
  199. log.error("删除aws文件失败,path=" + remoteFolderPath, e);
  200. }
  201. }
  202. @Override
  203. public void uploadMulFiles(String bucket, Map<String, String> filepaths){
  204. try {
  205. for (Map.Entry<String, String> entry : filepaths.entrySet()) {
  206. uploadFile(bucket, entry.getKey(), entry.getValue(),null);
  207. }
  208. } catch (Exception e) {
  209. log.error("OSS批量上传文件失败!");
  210. }
  211. }
  212. @Override
  213. public List<String> listRemoteFiles(String bucket, String sourcePath) {
  214. List<String> keyList = new ArrayList<>();
  215. try {
  216. boolean flag = true;
  217. String nextMaker = null;
  218. ListObjectsRequest listObjectsRequest = new ListObjectsRequest();
  219. listObjectsRequest.setBucketName(bucket);
  220. listObjectsRequest.setPrefix(sourcePath);
  221. listObjectsRequest.setMaxKeys(200);
  222. do {
  223. listObjectsRequest.setMarker(nextMaker);
  224. ObjectListing objectListing = s3.listObjects(listObjectsRequest);
  225. List<S3ObjectSummary> objectSummaries = objectListing.getObjectSummaries();
  226. List<String> collect = objectSummaries.stream().map(S3ObjectSummary::getKey).collect(Collectors.toList());
  227. if (CollUtil.isNotEmpty(collect)) {
  228. keyList.addAll(collect);
  229. }
  230. nextMaker = objectListing.getNextMarker();
  231. flag = objectListing.isTruncated();
  232. } while (flag);
  233. } catch (Exception e) {
  234. log.error("获取文件列表失败,path=" + sourcePath, e);
  235. e.printStackTrace();
  236. }
  237. return keyList;
  238. }
  239. @Override
  240. public void copyFileBetweenBucket(String sourceBucketName, String sourcePath, String targetBucketName, String targetPath){
  241. try {
  242. List<String> files = listRemoteFiles(sourceBucketName, sourcePath);
  243. if (ObjectUtils.isEmpty(files)) {
  244. return;
  245. }
  246. files.stream().forEach(file -> {
  247. CopyObjectRequest request = new CopyObjectRequest(sourceBucketName, file, targetBucketName, file.replace(sourcePath, targetPath));
  248. request.withCannedAccessControlList(CannedAccessControlList.PublicRead);
  249. s3.copyObject(request);
  250. });
  251. } catch (Exception e) {
  252. log.error("列举文件目录失败,key=" + sourcePath);
  253. }
  254. }
  255. @Override
  256. public void copyFilesBetweenBucket(String sourceBucketName, String targetBucketName, Map<String, String> pathMap){
  257. if (ObjectUtils.isEmpty(pathMap)) {
  258. return;
  259. }
  260. try {
  261. for (Map.Entry<String, String> entry : pathMap.entrySet()) {
  262. copyFileBetweenBucket(sourceBucketName, entry.getKey(), targetBucketName, entry.getValue());
  263. }
  264. } catch (Exception e) {
  265. log.error("批量复制文件失败!");
  266. }
  267. }
  268. @Override
  269. public String getFileContent(String bucketName, String remoteFilePath){
  270. try (S3Object object = s3.getObject(bucketName,remoteFilePath);
  271. S3ObjectInputStream inputStream = object.getObjectContent()){
  272. StringBuilder content = new StringBuilder();
  273. try(BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream))){
  274. while (true) {
  275. String line = reader.readLine();
  276. if (line == null) break;
  277. content.append(line);
  278. }
  279. } catch (IOException e) {
  280. log.error("读取aws文件流失败", e);
  281. }
  282. return content.toString();
  283. } catch (Exception e) {
  284. log.error("获取文件内容失败:{}", remoteFilePath, e);
  285. return null;
  286. }
  287. }
  288. @Override
  289. public boolean fileExist(String bucket, String objectName) {
  290. try {
  291. return s3.doesObjectExist(bucket, objectName);
  292. } catch (Exception e) {
  293. log.error("判断文件是否存在失败:{}", objectName);
  294. return false;
  295. }
  296. }
  297. @Override
  298. public void downloadFile(String bucket, String remoteFilePath, String localPath) {
  299. try {
  300. File localFile = new File(localPath);
  301. if (!localFile.getParentFile().exists()) {
  302. localFile.getParentFile().mkdirs();
  303. }
  304. if(localFile.isDirectory()){
  305. String fileName = remoteFilePath.substring(remoteFilePath.lastIndexOf("/")+1);
  306. log.info("未配置文件名,使用默认文件名:{}",fileName);
  307. localPath = localPath.concat(File.separator).concat(fileName);
  308. }
  309. GetObjectRequest request = new GetObjectRequest(bucket, remoteFilePath);
  310. s3.getObject(request,new File(localPath));
  311. } catch (Throwable throwable) {
  312. log.error("文件下载失败:{}", remoteFilePath);
  313. throwable.printStackTrace();
  314. }
  315. }
  316. @Override
  317. public URL getPresignedUrl(String bucket,String url) {
  318. java.util.Date expiration = new java.util.Date();
  319. long expTimeMillis = expiration.getTime();
  320. expTimeMillis += 1000 * 60 * 60 * 8;
  321. expiration.setTime(expTimeMillis);
  322. GeneratePresignedUrlRequest generatePresignedUrlRequest = new GeneratePresignedUrlRequest(bucket, url)
  323. .withMethod(HttpMethod.PUT).withExpiration(expiration);
  324. return s3.generatePresignedUrl(generatePresignedUrlRequest);
  325. }
  326. @Override
  327. public long getSubFileNums(String bucket, String url) {
  328. long totalFileNums = 0;
  329. try {
  330. boolean flag = true;
  331. String nextMaker = null;
  332. ListObjectsRequest listObjectsRequest = new ListObjectsRequest();
  333. listObjectsRequest.setBucketName(bucket);
  334. listObjectsRequest.setPrefix(url);
  335. listObjectsRequest.setMaxKeys(200);
  336. do {
  337. listObjectsRequest.setMarker(nextMaker);
  338. ObjectListing objectListing = s3.listObjects(listObjectsRequest);
  339. List<S3ObjectSummary> objectSummaries = objectListing.getObjectSummaries();
  340. List<String> collect = objectSummaries.stream().map(S3ObjectSummary::getKey).collect(Collectors.toList());
  341. totalFileNums = totalFileNums + collect.size();
  342. nextMaker = objectListing.getNextMarker();
  343. flag = objectListing.isTruncated();
  344. } while (flag);
  345. } catch (Exception e) {
  346. log.error("获取文件数量失败,path=" + url, e);
  347. e.printStackTrace();
  348. }
  349. return totalFileNums;
  350. }
  351. @Override
  352. public void restoreFolder(String bucket, String folderName, Integer priority) {
  353. List<String> objectList = this.listRemoteFiles(bucket, folderName);
  354. if(CollUtil.isEmpty(objectList)){
  355. return;
  356. }
  357. objectList.parallelStream().forEach(objectName -> {
  358. this.restoreFile(bucket, objectName, priority);
  359. });
  360. }
  361. @Override
  362. public void restoreFile(String bucket, String objectName, Integer priority){
  363. ObjectMetadata objectMetadata = s3.getObjectMetadata(bucket, objectName);
  364. // 校验Object是否为归档类型Object。
  365. StorageClass storageClass = StorageClass.fromValue(objectMetadata.getStorageClass());
  366. if (storageClass == StorageClass.Glacier) {
  367. Tier restoreTier = null;
  368. switch (priority){
  369. case 1 :
  370. restoreTier = Tier.Expedited;
  371. break;
  372. case 2 :
  373. restoreTier = Tier.Standard;
  374. break;
  375. default:
  376. restoreTier = Tier.Bulk;
  377. }
  378. RestoreObjectRequest requestRestore = new RestoreObjectRequest(bucket, objectName, 1);
  379. GlacierJobParameters glacierJobParameters = new GlacierJobParameters();
  380. glacierJobParameters.setTier(restoreTier);
  381. requestRestore.setGlacierJobParameters(glacierJobParameters);
  382. //开始解冻
  383. s3.restoreObjectV2(requestRestore);
  384. }
  385. }
  386. @Override
  387. public Boolean checkStore(String bucket, String url) {
  388. ObjectMetadata objectMetadata = s3.getObjectMetadata(bucket, url);
  389. return !isRestoreCompleted(objectMetadata);
  390. }
  391. private boolean isRestoreCompleted(ObjectMetadata objectMetadata){
  392. Date restoreExpirationTime = objectMetadata.getRestoreExpirationTime();
  393. if(Objects.nonNull(restoreExpirationTime) && restoreExpirationTime.after(Calendar.getInstance().getTime())){
  394. return true;
  395. }
  396. return false;
  397. }
  398. @Override
  399. public void restoreFolder(String bucket, String url) {
  400. ObjectMetadata objectMetadata ;
  401. List<String> objectList = this.listRemoteFiles(bucket, url);
  402. if(CollUtil.isEmpty(objectList)){
  403. return;
  404. }
  405. for (String objectName : objectList) {
  406. objectMetadata = s3.getObjectMetadata(bucket, objectName);
  407. // 校验Object是否为归档类型Object。
  408. StorageClass storageClass = StorageClass.fromValue(objectMetadata.getStorageClass());
  409. if (storageClass == StorageClass.Glacier) {
  410. // 解冻Object。
  411. RestoreObjectRequest requestRestore = new RestoreObjectRequest(bucket, url, 1);
  412. s3.restoreObjectV2(requestRestore);
  413. }
  414. }
  415. }
  416. @Override
  417. public Integer getRestoreFolderProcess(String bucket, String url) {
  418. ObjectMetadata objectMetadata ;
  419. List<String> objectList = this.listRemoteFiles(bucket, url);
  420. if(CollUtil.isEmpty(objectList)){
  421. return 100;
  422. }
  423. List<String> restoreFileList = new ArrayList<>();
  424. for (String objectName : objectList) {
  425. objectMetadata = s3.getObjectMetadata(bucket, objectName);
  426. if(this.isRestoreCompleted(objectMetadata)){
  427. restoreFileList.add(objectName);
  428. }
  429. }
  430. if(objectList.size() <= restoreFileList.size() ){
  431. return 100;
  432. }
  433. BigDecimal rite = new BigDecimal(restoreFileList.size()).divide(new BigDecimal(objectList.size()),2,BigDecimal.ROUND_HALF_UP);
  434. BigDecimal multiply = rite.multiply(new BigDecimal(100));
  435. return multiply.intValue();
  436. }
  437. @Override
  438. public Long getSpace(String bucket, String key) {
  439. List<String> keyList = new ArrayList<>();
  440. Long total = 0L;
  441. boolean flag = true;
  442. String nextMaker = null;
  443. ListObjectsRequest listObjectsRequest = new ListObjectsRequest();
  444. listObjectsRequest.setBucketName(bucket);
  445. listObjectsRequest.setPrefix(key);
  446. listObjectsRequest.setMaxKeys(200);
  447. do {
  448. listObjectsRequest.setMarker(nextMaker);
  449. ObjectListing objectListing = s3.listObjects(listObjectsRequest);
  450. List<S3ObjectSummary> objectSummaries = objectListing.getObjectSummaries();
  451. Long space = objectSummaries.stream().mapToLong(S3ObjectSummary::getSize).sum();
  452. total += space;
  453. nextMaker = objectListing.getNextMarker();
  454. flag = objectListing.isTruncated();
  455. } while (flag);
  456. return total;
  457. }
  458. @Override
  459. public void copyFileToArchive(String sourceBucketName, String sourcePath, String targetBucketName, String targetPath) {
  460. try {
  461. List<String> files = listRemoteFiles(sourceBucketName, sourcePath);
  462. if (ObjectUtils.isEmpty(files)) {
  463. return;
  464. }
  465. files.stream().forEach(file -> {
  466. CopyObjectRequest request = new CopyObjectRequest(sourceBucketName, file, targetBucketName, file.replace(sourcePath, targetPath));
  467. request.setStorageClass(StorageClass.Glacier);
  468. s3.copyObject(request);
  469. });
  470. } catch (Exception e) {
  471. log.error("复制文件或目录失败,key:" + sourcePath, e);
  472. }
  473. }
  474. public static void main(String[] args) {
  475. AmazonS3 amazonS3 = amazonS3();
  476. List<String> keyList = new ArrayList<>();
  477. boolean flag = true;
  478. String nextMaker = null;
  479. ListObjectsRequest listObjectsRequest = new ListObjectsRequest();
  480. listObjectsRequest.setBucketName("test-4dkankan");
  481. listObjectsRequest.setPrefix("test/KJ-t-ekRwoMX8XP");
  482. listObjectsRequest.setMaxKeys(200);
  483. do {
  484. listObjectsRequest.setMarker(nextMaker);
  485. ObjectListing objectListing = amazonS3.listObjects(listObjectsRequest);
  486. List<S3ObjectSummary> objectSummaries = objectListing.getObjectSummaries();
  487. List<String> collect = objectSummaries.stream().map(S3ObjectSummary::getKey).collect(Collectors.toList());
  488. if (CollUtil.isNotEmpty(collect)) {
  489. keyList.addAll(collect);
  490. }
  491. nextMaker = objectListing.getNextMarker();
  492. flag = objectListing.isTruncated();
  493. } while (flag);
  494. keyList.stream().forEach(file -> {
  495. CopyObjectRequest request = new CopyObjectRequest("test-4dkankan", file, "test-4dkk-bak", file.replace("test/KJ-t-ekRwoMX8XP", "test/KJ-t-ekRwoMX8XP"));
  496. request.setStorageClass(StorageClass.DeepArchive);
  497. amazonS3.copyObject(request);
  498. });
  499. }
  500. @Override
  501. public FileInfoVo getFileInfo(String bucket, String key) {
  502. S3Object s3Object = null;
  503. S3ObjectInputStream objectInputStream = null;
  504. try {
  505. // 1. 获取文件元数据
  506. GetObjectMetadataRequest metadataRequest = new GetObjectMetadataRequest(bucket, key);
  507. ObjectMetadata metadata = s3.getObjectMetadata(metadataRequest);
  508. Date lastModified = metadata.getLastModified();
  509. String eTag = metadata.getETag();
  510. Long size = metadata.getContentLength();
  511. String md5 = eTag != null ? eTag.replace("\"", "") : "";
  512. GetObjectRequest getObjectRequest = new GetObjectRequest(bucket, key);
  513. s3Object = s3.getObject(getObjectRequest);
  514. objectInputStream = s3Object.getObjectContent();
  515. String sha1 = MD5Checksum.getSHA1(objectInputStream);
  516. return new FileInfoVo(
  517. md5,
  518. sha1.toUpperCase(),
  519. lastModified.getTime(),
  520. size
  521. );
  522. } catch (Exception e) {
  523. log.error("处理S3文件信息异常 - bucket:{}, key:{}", bucket, key, e);
  524. } finally {
  525. closeQuietly(objectInputStream);
  526. closeQuietly(s3Object);
  527. }
  528. return null;
  529. }
  530. private void closeQuietly(S3ObjectInputStream stream) {
  531. if (stream != null) {
  532. try {
  533. stream.close();
  534. } catch (IOException e) {
  535. log.warn("关闭S3对象流时发生异常", e);
  536. }
  537. }
  538. }
  539. private void closeQuietly(S3Object s3Object) {
  540. if (s3Object != null) {
  541. try {
  542. s3Object.close();
  543. } catch (IOException e) {
  544. log.warn("关闭S3对象时发生异常", e);
  545. }
  546. }
  547. }
  548. }