温馨提示:这篇文章已超过405天没有更新,请注意相关的内容是否还可用!
摘要:,,本文介绍了Amazon S3 SDK for Java 2.x的最新API的简单使用。该SDK提供了方便的Java接口,使得开发者能够轻松地与Amazon S3云存储服务进行交互。通过简单的几步操作,包括安装SDK、创建S3客户端、配置访问凭证、上传和下载文件等,开发者就能够轻松地上传、下载和管理存储在Amazon S3上的数据。本文旨在帮助开发者快速了解并使用这一强大的工具,以实现对云存储的高效操作。
目录
创建存储桶
登录亚马逊控制台 查找服务“S3” 进入存储桶创建页面;
点击 “创建存储桶”进入创建页面;
获取密钥ID和密钥
点击右上方账户信息在下拉菜单中选择 “安全凭证”(Security credentials)进入我的安全凭证页面;
下滑找到 “访问密钥”标签 点击右侧 “创建访问密钥”按钮;
步骤一: “访问密钥最佳实践和替代方案” 选择适合自己的方案
步骤二:“设置描述标签”可不填
步骤三 “检索访问密钥“
关闭屏蔽公共访问权限
点击创建的存储桶名称进入详情页面后点击“权限”标签
找到 “屏蔽公共访问权限” 点击下方 “编辑” 按钮
取消勾选“阻止所有公开访问”然后点击下方 “保存更改” 按钮;在弹出的确认框中输入“确认”后点击“确认”按钮即可生效。
创建存储桶访问策略
点击创建的存储桶名称进入详情页面后点击“权限”标签
找到存储桶策略 -> 点击右侧“编辑”
创建如下访问策略
代码示例
首先导入依赖
工具类
国内使用s3的坑点:
亚马逊中国区,必须进行ICP 备案,申请开发80或443端口,否则是不能通过网址直接访问s3内部对象的。
备注:以下操作基于您已有AWS账户;
需要获取:存储桶名称、所选区域、密钥ID和密钥;
创建存储桶
登录亚马逊控制台 查找服务“S3” 进入存储桶创建页面;
点击 “创建存储桶”进入创建页面;
- 输入存储桶名称 、选择区域;
2. 其他设置保持默认即可;
3. 点击 “创建存储桶”,即可完成存储桶的创建;
获取密钥ID和密钥
点击右上方账户信息在下拉菜单中选择 “安全凭证”(Security credentials)进入我的安全凭证页面;
下滑找到 “访问密钥”标签 点击右侧 “创建访问密钥”按钮;
- 进入创建访问密钥之后
步骤一: “访问密钥最佳实践和替代方案” 选择适合自己的方案
- 勾选下方复选框
- 点击下一步;
步骤二:“设置描述标签”可不填
- 点击 “创建访问密钥”按钮即可创建密钥;
步骤三 “检索访问密钥“
- 点击“下载.csv文件“ 保存密钥ID和密钥
- 注意:请保存好下载的.csv文件,离开此页面后“密钥”将没有地方获取查看;
关闭屏蔽公共访问权限
点击创建的存储桶名称进入详情页面后点击“权限”标签
找到 “屏蔽公共访问权限” 点击下方 “编辑” 按钮
取消勾选“阻止所有公开访问”然后点击下方 “保存更改” 按钮;在弹出的确认框中输入“确认”后点击“确认”按钮即可生效。
创建存储桶访问策略
点击创建的存储桶名称进入详情页面后点击“权限”标签
找到存储桶策略 -> 点击右侧“编辑”
创建如下访问策略
{ "Version": "2012-10-17", "Id": "GetImgAndPdf", "Statement": [ { "Sid": "GetImgAndPdf123", "Effect": "Allow", "Principal": { "AWS": "*" }, "Action": "s3:GetObject", "Resource": "arn:aws-cn:s3:::所创建存储桶名称/*" } ] }
代码示例
首先导入依赖
software.amazon.awssdk bom ${awsjavasdk.version} pom import software.amazon.awssdk s3 software.amazon.awssdk kms software.amazon.awssdk s3control software.amazon.awssdk s3-transfer-manager software.amazon.awssdk.crt aws-crt 0.24.0
工具类
package com.trainingos.file.utils; import com.trainingos.common.util.StringUtils; import com.trainingos.common.util.file.FileTypeUtils; import lombok.extern.slf4j.Slf4j; import org.apache.commons.io.FilenameUtils; import org.apache.http.entity.ContentType; import org.springframework.mock.web.MockMultipartFile; import org.springframework.web.multipart.MultipartFile; import software.amazon.awssdk.core.sync.RequestBody; import software.amazon.awssdk.services.s3.*; import software.amazon.awssdk.services.s3.model.*; import software.amazon.awssdk.services.s3.presigner.S3Presigner; import software.amazon.awssdk.services.s3.presigner.model.GetObjectPresignRequest; import software.amazon.awssdk.services.s3.presigner.model.PresignedGetObjectRequest; import java.io.*; import java.nio.charset.Charset; import java.nio.file.Path; import java.time.Duration; import java.util.ArrayList; import java.util.List; import java.util.Objects; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; import java.util.zip.ZipInputStream; /** * @Description 亚马逊文件上传工具类 * @Author ajie **/ @Slf4j public class FileS3Utils { /** * 密钥ID */ @Value("${aws.s3.accessKeyId}") private String accessKeyId; /** * 密钥 */ @Value("${aws.s3.secretKey}") private String secretKey; /*@Value("${aws.s3.s3Uri}") private String s3Uri;*/ /** * 存储桶名字 */ @Value("${aws.s3.bucket}") private String bucketName; /** * 地区节点 */ @Value("${aws.s3.region}") private String regionCode; /** * 资源映射前缀 */ @Value("${aws.s3.path}") private String filePathPrefix; public static String S3_ACCESS_KEY_ID = null; public static String S3_SECRET_KEY = null; //public static String S3_URI = null; public static String S3_BUCKET = null; public static String S3_REGION = null; public static String S3_PATH_PREFIX = null; /** * 初始化 */ @PostConstruct public void init() { S3_ACCESS_KEY_ID = accessKeyId; S3_SECRET_KEY = secretKey; //S3_URI = s3Uri; S3_BUCKET = bucketName; S3_REGION = regionCode; S3_PATH_PREFIX = filePathPrefix; } /** * S3客户端对象 */ private static S3Client s3Client; public static S3TransferManager transferManager; /** * 预签名对象 */ private static S3Presigner s3Presigner; /** * 获取S3客户端对象 * * @return S3Client */ public static synchronized S3Client getS3Client() { if (null == s3Client) { s3Client = S3Client.builder() .credentialsProvider(StaticCredentialsProvider.create(AwsBasicCredentials.create(S3_ACCESS_KEY_ID, S3_SECRET_KEY))) //.endpointConfiguration(new AwsClientBuilder.EndpointConfiguration(hostName, region)) // 如果有endpoint,可以用这个,这个和withRegion(Region)不能一起使用 //.withPathStyleAccessEnabled(true) // 如果配置了S3域名,就需要加这个进行路径访问,要不然会报AccessKey不存在的问题 .region(Region.of(S3_REGION)) .build(); } return s3Client; } /** * 上传大文件 高级API * @return */ private static synchronized S3TransferManager getTransferManager(){ if(null == transferManager){ S3AsyncClient s3AsyncClient = S3AsyncClient.crtBuilder() .credentialsProvider(StaticCredentialsProvider.create(AwsBasicCredentials.create(S3_ACCESS_KEY_ID, S3_SECRET_KEY))) .region(Region.of(S3_REGION)) //.targetThroughputInGbps(20.0) //.minimumPartSizeInBytes(8 * MB) .build(); transferManager = S3TransferManager.builder() .s3Client(s3AsyncClient) .build(); } return transferManager; } /** * 获取预签名对象 * * @return */ public static synchronized S3Presigner getS3PreSigner() { if (null == s3Presigner) { s3Presigner = S3Presigner.builder() // 凭证 .credentialsProvider(StaticCredentialsProvider.create(AwsBasicCredentials.create(S3_ACCESS_KEY_ID, S3_SECRET_KEY))) //.endpointOverride(URI.create(S3_URI)) // 服务配置 //.serviceConfiguration(S3Configuration.builder().checksumValidationEnabled(false).pathStyleAccessEnabled(true).build()) // 区域 .region(Region.of(S3_REGION)) .build(); } return s3Presigner; } /** * 上传文件 * * @param s3 * @param bucketName * @param awsFilePrefix aws资源映射前缀 * @param file * @param catalog * @return * @throws IOException */ public static String uploadPublicFile(S3Client s3, String bucketName, String awsFilePrefix, MultipartFile file, String catalog) throws IOException { // 生成新文件名 String fileName = FileUploadUtils.extractFilename(file); try { String keyName = awsFilePrefix + catalog + "/" + fileName; log.info("keyName===》 {} ", keyName); String contentType = FileTypeUtils.getFileType(fileName); log.info("文件类型===》 {} ", contentType); // 使用PutObjectRequest来设置附加的值 PutObjectRequest putObjectRequest = PutObjectRequest.builder() .bucket(bucketName) .key(keyName) .contentType(contentType) .contentLength(file.getSize()) .acl(ObjectCannedACL.PUBLIC_READ) .build(); // 上传文件 s3.putObject(putObjectRequest, RequestBody.fromBytes(file.getBytes())); log.info("======上传成功=======》 {} ", catalog + "/" + fileName); return catalog + "/" + fileName; } catch (S3Exception | IOException e) { log.info("上传文件:", e); throw new IOException(e.getMessage(), e); } } /** * 预览 有效时间为1天 * * @param key 文件地址 桶中文件全路径 * @return */ private static String getPreSignatureUrl(S3Presigner s3Presigner, String bucketName, String key) throws Exception { String preSignatureUrl = ""; try { GetObjectRequest getObjectRequest = GetObjectRequest.builder() .bucket(bucketName) .key(key) .build(); //设置预签名URL可访问时间 1天 GetObjectPresignRequest getObjectPresignRequest = GetObjectPresignRequest.builder() .signatureDuration(Duration.ofDays(1)) .getObjectRequest(getObjectRequest) .build(); PresignedGetObjectRequest presignedGetObjectRequest = s3Presigner.presignGetObject(getObjectPresignRequest); preSignatureUrl = String.valueOf(presignedGetObjectRequest.url()); } catch (Exception e) { log.info("生成预签名URL失败,异常: ", e); throw new Exception(e.getMessage(), e); } return preSignatureUrl; } /** * 检查对象是否存在 * * @param s3Client s3客户端 * @param key 文件在桶中的全路径地址 * @return */ public static boolean checkIfObjectExists(S3Client s3Client, String bucketName, String key) { try { HeadObjectRequest headObjectRequest = HeadObjectRequest.builder() .bucket(bucketName) .key(key) .build(); s3Client.headObject(headObjectRequest); return true; // 对象存在 } catch (NoSuchKeyException e) { return false; // 对象不存在 } catch (S3Exception e) { log.info("Error checking if object exists: ", e); return false; // 其他错误 } } /** * 流的方式上传文件到s3桶 * * @param s3Client * @param bucketName * @param key * @param file */ public static void uploadFileStream(S3Client s3Client, String bucketName, String key, File file) { try { FileInputStream fileInputStream = new FileInputStream(file); PutObjectRequest objectRequest = PutObjectRequest.builder() .bucket(bucketName) .key(key) .build(); // 使用 RequestBody.fromInputStream 方法将文件流上传到 S3 s3Client.putObject(objectRequest, RequestBody.fromInputStream(fileInputStream, file.length())); System.out.println("File uploaded to S3 successfully."); } catch (Exception e) { System.err.println("Error uploading file to S3: " + e.getMessage()); } } /** * 获取桶中某目录下所有文件 * * @param s3Client * @param bucketName * @param prefix 指定前缀,例如文件夹路径 * @return */ public static List listFilesInBucket(S3Client s3Client, String bucketName, String prefix) { ListObjectsV2Request listObjectsRequest = ListObjectsV2Request.builder() .bucket(bucketName) .prefix(prefix) .build(); ListObjectsV2Response response = s3Client.listObjectsV2(listObjectsRequest); return response.contents(); } /** * 上传对象 */ // public static void main(String[] args){ // // try{ // Long start = System.currentTimeMillis(); // String baseUrl = "upload/images/common/"; // // //File file = new File("C://Users//阿杰//Pictures//微信图片_20220106110701.png"); // File file = new File("C://Users//阿杰//Videos//《历史关头——红色纪念馆之旅》第二集:星星之火,可以燎原.mp4"); // // boolean b = checkIfObjectExists(getS3Client(), "《历史关头——红色纪念馆之旅》第二集:星星之火,可以燎原.mp4"); // if(b){ // log.info("============文件已存在====="); // return; // } // //multipartUpload(baseUrl + "/《历史关头——红色纪念馆之旅》第二集:星星之火,可以燎原.mp4",file); // // //MultipartFile multipartFile = getMultipartFile(file); // // //String address = uploadPublicFile(baseUrl, multipartFile); // log.info("===========上传完成=====用时:{}",(double)(System.currentTimeMillis()-start)/1000); // //log.info("=========文件地址=====》 {} ", address); // // //String upload = FileUploadUtils.upload("D:/wenjian/project" + File.separator + "png", multipartFile); // //log.info("=========文件地址=====》 {} ", upload); // // log.info("================================================"); // // //String preview = getPreSignatureUrl(baseUrl + "2023/11/06/《历史关头——红色纪念馆之旅》第二集:星星之火,可以燎原_20231106150748A001.mp4"); // //log.info("=========文件预览地址=====》 {} ", preview); // // //getURL(baseUrl + "《历史关头——红色纪念馆之旅》第二集:星星之火,可以燎原.mp4"); // // //=================================================== // }catch (Exception e){ // log.info("============",e); // } // } /** * file 转 MultipartFile * * @param file * @return */ public static MultipartFile converFileToMultipartFile(File file) throws IOException { InputStream inputStream = new FileInputStream(file); return new MockMultipartFile(file.getName(), file.getName(), ContentType.APPLICATION_OCTET_STREAM.toString(), inputStream); } /** * 转换 MultipartFile 为 File 对象 * * @param multipartFile * @return * @throws IOException */ public static File convertMultipartFileToFile(MultipartFile multipartFile) throws IOException { File file = new File(Objects.requireNonNull(multipartFile.getOriginalFilename())); try (OutputStream os = new FileOutputStream(file)) { os.write(multipartFile.getBytes()); } return file; } private static final long PART_SIZE = 100 * 1024 * 1024; // 设置文件分段大小 100 M /** * 计算分段数量 */ public static long getPartNumber(long fileLength) { if (fileLength % PART_SIZE == 0) { return fileLength / PART_SIZE; } else { return fileLength / PART_SIZE + 1; } } private static void multipartUpload(S3Client s3Client, String bucketName, String objectKey, File file) { CreateMultipartUploadRequest createMultipartUploadRequest = CreateMultipartUploadRequest.builder() .bucket(bucketName) .key(objectKey) .build(); CreateMultipartUploadResponse response = s3Client.createMultipartUpload(createMultipartUploadRequest); String uploadId = response.uploadId(); try { FileInputStream fis = new FileInputStream(file); List completedParts = new ArrayList(); final long fileLength = file.length(); final long partNumber = getPartNumber(fileLength); log.info("multipartUpload fileLength={}, partNumber={},uploadId={}", fileLength, partNumber, uploadId); for (int i = 1; i part.partNumber()) .sum() * partSize; try { long contentLength = filePath.toFile().length(); for (; filePosition b.bucket(bucketName).key(keyName)) .addTransferListener(LoggingTransferListener.create()) //.source(file.) .build(); FileUpload fileUpload = transferManager.uploadFile(uploadFileRequest); CompletedFileUpload uploadResult = fileUpload.completionFuture().join(); String s = uploadResult.response().eTag(); return s; }catch (Exception e){ log.info("======",e); } return ""; }*/ /** * 上传大文件 * @param transferManager * @param bucketName * @param key * @param filePath * @return */ /*public String uploadFile(S3TransferManager transferManager, String bucketName, String key, String filePath) { UploadFileRequest uploadFileRequest = UploadFileRequest.builder() .putObjectRequest(b -> b.bucket(bucketName).key(key)) .addTransferListener(LoggingTransferListener.create()) .source(Paths.get(filePath)) .build(); FileUpload fileUpload = transferManager.uploadFile(uploadFileRequest); CompletedFileUpload uploadResult = fileUpload.completionFuture().join(); return uploadResult.response().eTag(); }*/ }
国内使用s3的坑点:
亚马逊中国区,必须进行ICP 备案,申请开发80或443端口,否则是不能通过网址直接访问s3内部对象的。
- 点击 “创建访问密钥”按钮即可创建密钥;
还没有评论,来说两句吧...