S3FileService.java 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304
  1. package com.fdkankan.fyun.s3;
  2. import cn.hutool.core.collection.CollUtil;
  3. import com.amazonaws.HttpMethod;
  4. import com.amazonaws.services.s3.AmazonS3;
  5. import com.amazonaws.services.s3.model.*;
  6. import com.fdkankan.fyun.constant.FYunTypeEnum;
  7. import com.fdkankan.fyun.face.AbstractFYunFileService;
  8. import org.apache.commons.lang3.StringUtils;
  9. import org.slf4j.Logger;
  10. import org.slf4j.LoggerFactory;
  11. import org.springframework.beans.factory.annotation.Autowired;
  12. import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
  13. import org.springframework.stereotype.Component;
  14. import org.springframework.util.ObjectUtils;
  15. import java.io.*;
  16. import java.net.URL;
  17. import java.util.ArrayList;
  18. import java.util.List;
  19. import java.util.Map;
  20. import java.util.stream.Collectors;
  21. @Component
  22. @ConditionalOnProperty(name = "fyun.type",havingValue = "aws")
  23. public class S3FileService extends AbstractFYunFileService {
  24. private Logger log = LoggerFactory.getLogger(this.getClass().getName());
  25. @Autowired
  26. private AmazonS3 s3;
  27. @Override
  28. public String uploadFile(String bucket, byte[] data, String remoteFilePath){
  29. try {
  30. ObjectMetadata metadata = new ObjectMetadata();
  31. PutObjectRequest request = new PutObjectRequest(bucket, remoteFilePath, new ByteArrayInputStream(data), metadata);
  32. request.withCannedAcl(CannedAccessControlList.PublicRead);
  33. s3.putObject(request);
  34. } catch (Exception e) {
  35. log.error("s3上传文件失败", e);
  36. }
  37. return null;
  38. }
  39. @Override
  40. public String uploadFile(String bucket, String filePath, String remoteFilePath){
  41. return uploadFile(bucket, filePath, remoteFilePath,null);
  42. }
  43. @Override
  44. public String uploadFile(String bucket, InputStream inputStream, String remoteFilePath) {
  45. try {
  46. s3.putObject(bucket, remoteFilePath, inputStream, null);
  47. } catch (Exception e) {
  48. log.error("文件流上传失败,目标路径:{}", remoteFilePath);
  49. e.printStackTrace();
  50. }
  51. return null;
  52. }
  53. @Override
  54. public String uploadFile(String bucket, String filePath, String remoteFilePath,Map<String, String> headers){
  55. try {
  56. File file = new File(filePath);
  57. if (!file.exists()) {
  58. log.error("要上传的文件不存在:" + filePath);
  59. return null;
  60. }
  61. // 设置文件并设置公读
  62. ObjectMetadata metadata = new ObjectMetadata();
  63. if (filePath.contains(".jpg")) {
  64. metadata.setContentType("image/jpeg");
  65. }
  66. if (filePath.contains(".png")) {
  67. metadata.setContentType("image/png");
  68. }
  69. if(org.apache.commons.lang3.ObjectUtils.isNotEmpty(headers)){
  70. for (Map.Entry<String, String> header : headers.entrySet()) {
  71. metadata.setHeader(header.getKey(),header.getValue());
  72. }
  73. }
  74. PutObjectRequest request = new PutObjectRequest(bucket, remoteFilePath, file);
  75. request.withCannedAcl(CannedAccessControlList.PublicRead);
  76. request.withMetadata(metadata);
  77. // 上传文件
  78. PutObjectResult putObjectResult = s3.putObject(request);
  79. if (StringUtils.isNotEmpty(putObjectResult.getETag())) {
  80. log.info("s3上传文件成功:" + remoteFilePath);
  81. }
  82. } catch (Exception e) {
  83. log.error("文件上传失败:{}",filePath);
  84. e.printStackTrace();
  85. }
  86. return null;
  87. }
  88. @Override
  89. public String uploadFileByCommand(String bucket, String filePath, String remoteFilePath){
  90. try {
  91. String optType = new File(filePath).isDirectory() ? "folder" : "file";
  92. String command = String.format(fYunConstants.UPLOAD_SH, bucket, filePath, remoteFilePath, FYunTypeEnum.AWS.code(), optType);
  93. log.info("开始上传文件, ossPath:{}, srcPath:{}", remoteFilePath, filePath);
  94. callshell(command);
  95. } catch (Exception e) {
  96. log.error("上传文件失败, ossPath:{}, srcPath:{}", remoteFilePath, filePath);
  97. e.printStackTrace();
  98. }
  99. return null;
  100. }
  101. @Override
  102. public void downloadFileByCommand(String bucket, String filePath, String remoteFilePath) {
  103. try {
  104. String optType = remoteFilePath.contains(".") ? "file" : "folder";
  105. String command = String.format(fYunConstants.DOWNLOAD_SH, bucket, remoteFilePath, filePath, FYunTypeEnum.AWS.code(), optType);
  106. log.info("开始下载文件, ossPath:{}, srcPath:{}", remoteFilePath, filePath);
  107. callshell(command);
  108. } catch (Exception e) {
  109. log.error("上传文件失败, ossPath:{}, srcPath:{}", remoteFilePath, filePath);
  110. e.printStackTrace();
  111. }
  112. }
  113. @Override
  114. public void deleteFile(String bucket, String remoteFilePath){
  115. if (remoteFilePath.startsWith("/")) {
  116. remoteFilePath = remoteFilePath.substring(1);
  117. }
  118. try {
  119. s3.deleteObject(bucket, remoteFilePath);
  120. } catch (Exception e) {
  121. log.error("s3删除文件失败,key=" + remoteFilePath, e);
  122. }
  123. }
  124. @Override
  125. public void deleteFolder(String bucket, String remoteFolderPath){
  126. try {
  127. int maxKeys = 200;
  128. String nextMaker = null;
  129. ListObjectsRequest listObjectsRequest = new ListObjectsRequest();
  130. listObjectsRequest.setBucketName(bucket);
  131. listObjectsRequest.setPrefix(remoteFolderPath);
  132. listObjectsRequest.setMaxKeys(maxKeys);
  133. com.amazonaws.services.s3.model.ObjectListing objectListing;
  134. do {
  135. listObjectsRequest.setMarker(nextMaker);
  136. objectListing = s3.listObjects(listObjectsRequest);
  137. List<S3ObjectSummary> objectSummaries = objectListing.getObjectSummaries();
  138. List<DeleteObjectsRequest.KeyVersion> keys = objectSummaries.stream().map(summary -> new DeleteObjectsRequest.KeyVersion(summary.getKey())).collect(Collectors.toList());
  139. DeleteObjectsRequest multiObjectDeleteRequest = new DeleteObjectsRequest(bucket)
  140. .withKeys(keys).withQuiet(false);
  141. DeleteObjectsResult delObjRes = s3.deleteObjects(multiObjectDeleteRequest);
  142. int successfulDeletes = delObjRes.getDeletedObjects().size();
  143. log.info("删除aws文件成功,删除文件数;{}", successfulDeletes);
  144. nextMaker = objectListing.getNextMarker();
  145. } while (objectListing.isTruncated());
  146. } catch (Exception e) {
  147. log.error("删除was文件失败,path=" + remoteFolderPath, e);
  148. }
  149. }
  150. @Override
  151. public void uploadMulFiles(String bucket, Map<String, String> filepaths){
  152. try {
  153. for (Map.Entry<String, String> entry : filepaths.entrySet()) {
  154. uploadFile(bucket, entry.getKey(), entry.getValue(),null);
  155. }
  156. } catch (Exception e) {
  157. log.error("OSS批量上传文件失败!");
  158. }
  159. }
  160. @Override
  161. public List<String> listRemoteFiles(String bucket, String sourcePath) {
  162. List<String> keyList = new ArrayList<>();
  163. try {
  164. boolean flag = true;
  165. String nextMaker = null;
  166. ListObjectsRequest listObjectsRequest = new ListObjectsRequest();
  167. listObjectsRequest.setBucketName(bucket);
  168. listObjectsRequest.setPrefix(sourcePath);
  169. listObjectsRequest.setMaxKeys(200);
  170. do {
  171. listObjectsRequest.setMarker(nextMaker);
  172. ObjectListing objectListing = s3.listObjects(listObjectsRequest);
  173. List<S3ObjectSummary> objectSummaries = objectListing.getObjectSummaries();
  174. List<String> collect = objectSummaries.stream().map(S3ObjectSummary::getKey).collect(Collectors.toList());
  175. if (CollUtil.isNotEmpty(collect)) {
  176. keyList.addAll(collect);
  177. }
  178. nextMaker = objectListing.getNextMarker();
  179. flag = objectListing.isTruncated();
  180. } while (flag);
  181. } catch (Exception e) {
  182. log.error("获取文件列表失败,path=" + sourcePath, e);
  183. e.printStackTrace();
  184. }
  185. return keyList;
  186. }
  187. @Override
  188. public void copyFileBetweenBucket(String sourceBucketName, String sourcePath, String targetBucketName, String targetPath){
  189. try {
  190. List<String> files = listRemoteFiles(sourceBucketName, sourcePath);
  191. if (ObjectUtils.isEmpty(files)) {
  192. log.error("源文件夹为空:{}", sourcePath);
  193. }
  194. files.stream().forEach(file -> {
  195. CopyObjectRequest request = new CopyObjectRequest(sourceBucketName, file, targetBucketName, file.replace(sourcePath, targetPath));
  196. request.withCannedAccessControlList(CannedAccessControlList.PublicRead);
  197. s3.copyObject(request);
  198. });
  199. } catch (Exception e) {
  200. log.error("列举文件目录失败,key=" + sourcePath);
  201. }
  202. }
  203. @Override
  204. public void copyFilesBetweenBucket(String sourceBucketName, String targetBucketName, Map<String, String> pathMap){
  205. if (ObjectUtils.isEmpty(pathMap)) {
  206. return;
  207. }
  208. try {
  209. for (Map.Entry<String, String> entry : pathMap.entrySet()) {
  210. copyFileBetweenBucket(sourceBucketName, entry.getKey(), targetBucketName, entry.getValue());
  211. }
  212. } catch (Exception e) {
  213. log.error("批量复制文件失败!");
  214. }
  215. }
  216. @Override
  217. public String getFileContent(String bucketName, String remoteFilePath){
  218. try {
  219. GetObjectRequest request = new GetObjectRequest(bucketName,remoteFilePath);
  220. S3Object object = s3.getObject(request);
  221. S3ObjectInputStream inputStream = object.getObjectContent();
  222. StringBuilder content = new StringBuilder();
  223. try(BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream))){
  224. while (true) {
  225. String line = reader.readLine();
  226. if (line == null) break;
  227. content.append(line);
  228. }
  229. } catch (IOException e) {
  230. log.error("读取aws文件流失败", e);
  231. }
  232. object.close();
  233. return content.toString();
  234. } catch (Exception e) {
  235. log.error("获取文件内容失败:{}", remoteFilePath);
  236. return null;
  237. }
  238. }
  239. @Override
  240. public boolean fileExist(String bucket, String objectName) {
  241. try {
  242. return s3.doesObjectExist(bucket, objectName);
  243. } catch (Exception e) {
  244. log.error("判断文件是否存在失败:{}", objectName);
  245. return false;
  246. }
  247. }
  248. @Override
  249. public void downloadFile(String bucket, String remoteFilePath, String localPath) {
  250. try {
  251. File localFile = new File(localPath);
  252. if (!localFile.getParentFile().exists()) {
  253. localFile.getParentFile().mkdirs();
  254. }
  255. if(localFile.isDirectory()){
  256. String fileName = remoteFilePath.substring(remoteFilePath.lastIndexOf("/")+1);
  257. log.info("未配置文件名,使用默认文件名:{}",fileName);
  258. localPath = localPath.concat(File.separator).concat(fileName);
  259. }
  260. GetObjectRequest request = new GetObjectRequest(bucket, remoteFilePath);
  261. s3.getObject(request,new File(localPath));
  262. } catch (Throwable throwable) {
  263. log.error("文件下载失败:{}", remoteFilePath);
  264. throwable.printStackTrace();
  265. }
  266. }
  267. @Override
  268. public URL getPresignedUrl(String bucket,String url) {
  269. java.util.Date expiration = new java.util.Date();
  270. long expTimeMillis = expiration.getTime();
  271. expTimeMillis += 1000 * 60 * 60 * 8;
  272. expiration.setTime(expTimeMillis);
  273. GeneratePresignedUrlRequest generatePresignedUrlRequest = new GeneratePresignedUrlRequest(bucket, url)
  274. .withMethod(HttpMethod.PUT).withExpiration(expiration);
  275. return s3.generatePresignedUrl(generatePresignedUrlRequest);
  276. }
  277. }