
AWS SDK for Java v2 S3 Transfer Manager 完全指南大文件并行传输、进度监听与断点续传实战【免费下载链接】aws-sdk-java-v2The official AWS SDK for Java - Version 2项目地址: https://gitcode.com/GitHub_Trending/aw/aws-sdk-java-v2本文基于 AWS SDK for Java v2 仓库中 services-custom/s3-transfer-manager/README.md 展开完整覆盖 S3 Transfer Manager 的依赖配置、实例化方式、单对象/目录上传下载与复制等核心用法并结合模块源码补充了 Builder 配置参数、TransferListener 监听生命周期、暂停/恢复pause resume机制以及底层客户端选择逻辑帮助你把大文件传输的吞吐量、可观测性和可靠性一次性做好。一、模块定位为什么需要 S3 Transfer ManagerREADME 对该模块的定义是一个构建在异步 S3 客户端之上的高层传输工具提供简洁的 API 完成应用与 Amazon S3 之间的文件、目录传输并支持实时监控传输进度和暂停传输以便稍后继续。从接口 JavadocS3TransferManager.java可以看到更完整的表述它借助 Amazon S3 的**分片上传multipart upload和字节范围请求byte-range fetch**实现并行传输从而获得更高的吞吐量和可靠性。该模块的 Maven 坐标与依赖声明见 services-custom/s3-transfer-manager/pom.xmlartifactId 为s3-transfer-manager最低要求 JRE 1.8其中software.amazon.awssdk.crt:aws-crt被声明为optionaltrue/optional源码注释标明Only required for CRT-based TM——也就是说 CRT 是可选依赖没有它时 SDK 会退回到 Java 原生分片实现。二、添加依赖按照 README 的 Getting Started 部分项目需要同时引入两个依赖dependency groupIdsoftware.amazon.awssdk/groupId artifactIds3-transfer-manager/artifactId version${awsjavasdk.version}/version /dependency dependency groupIdsoftware.amazon.awssdk.crt/groupId artifactIdaws-crt/artifactId version${awscrt.version}/version /dependency记得把${awsjavasdk.version}和${awscrt.version}替换为你实际使用的最新版本号。s3-transfer-manager会自动传递依赖s3、sdk-core、utils等核心模块因此无需单独再引入s3服务模块。三、实例化 Transfer Manager3.1 使用默认设置最简单的方式是一行代码创建S3TransferManager transferManager S3TransferManager.create();此时底层用哪个 S3 客户端由类路径上是否存在 AWS CRT决定。这一行为可以在工厂类 TransferManagerFactory.java 中得到印证private static SupplierS3AsyncClient defaultS3AsyncClient() { if (crtInClasspath()) { return S3AsyncClient::crtCreate; // 类路径有 CRT创建 CRT 客户端 } return S3AsyncClient.builder().multipartEnabled(true)::build; // 否则Java 原生分片客户端 } private static boolean crtInClasspath() { try { ClassLoaderHelper.loadClass(software.amazon.awssdk.crt.s3.S3Client, false); } catch (ClassNotFoundException e) { return false; } return true; }即检测到software.amazon.awssdk.crt.s3.S3Client类存在时使用S3AsyncClient.crtCreate()否则退回到启用了 multipart 的 Java 客户端。接口 Javadoc 也明确建议添加aws-crt依赖以启用自动分片特性。3.2 使用 Builder 自定义 CRT S3 客户端README 给出的自定义示例S3AsyncClient s3AsyncClient S3AsyncClient.crtBuilder() .credentialsProvider(DefaultCredentialsProvider.create()) .region(Region.US_WEST_2) .targetThroughputInGbps(20.0) .minimumPartSizeInBytes(8 * MB) .build(); S3TransferManager transferManager S3TransferManager.builder() .s3Client(s3AsyncClient) .build();其中MB来自模块提供的常量类 SizeConstant.javaKB 1024、MB 1024 * KB、GB 1024 * MB。targetThroughputInGbps(20.0)表示目标吞吐 20 GbpsminimumPartSizeInBytes(8 * MB)表示最小分片 8 MiB——这两个参数共同决定了 CRT 客户端如何把大对象切分并行传输。Javadoc 还展示了第三条路不使用 CRT而是采用 Java 原生分片客户端与 CRT 客户端提供相同的分片上传/下载能力S3AsyncClient s3AsyncClient S3AsyncClient.builder() .multipartEnabled(true) .multipartConfiguration(conf - conf.apiCallBufferSizeInBytes(32 * MB)) .build(); S3TransferManager transferManager S3TransferManager.builder() .s3Client(s3AsyncClient) .build();build()时的实现选择逻辑见 TransferManagerFactory.createTransferManager若客户端是S3CrtAsyncClient则创建CrtS3TransferManager若既不是 CRT 客户端也不是 Java 分片客户端会记录 debug 日志提示分片上传/下载特性可能未启用、可恢复上传可能不受支持并创建通用的GenericS3TransferManager。3.3 Builder 的完整配置项S3TransferManager.Builder定义于 S3TransferManager.java支持以下配置配置项作用默认值s3Client(S3AsyncClient)指定底层 S3 异步客户端官方强烈建议用S3AsyncClient.crtBuilder()创建以获得分片传输与最大吞吐未提供时自动创建按是否含 CRT 决定类型executor(Executor)执行后台任务的线程池如目录上传时的文件树遍历未提供时 SDK 自建线程池uploadDirectoryFollowSymbolicLinks(Boolean)uploadDirectory遍历时是否跟随符号链接falseuploadDirectoryMaxDepth(Integer)uploadDirectory遍历的最大目录层数1表示只访问源目录直接包含的文件Integer.MAX_VALUEtransferDirectoryMaxConcurrency(Integer)一次目录上传/下载操作内并发的文件传输数上限100两个容易踩坑的点源码中有明确说明通过s3Client(...)传入的客户端不会随 Transfer Manager 的close()关闭必须由调用方自行关闭通过executor(...)传入的线程池同样由用户负责关闭SDK 不会替你关。默认线程池的实现在 TransferManagerConfiguration.java核心线程 0、最大 100 线程、空闲 60 秒回收、队列容量 1000线程名前缀s3-transfer-manager。此外请求级配置优先于客户端级配置——例如UploadDirectoryRequest.followSymbolicLinks(...)会覆盖 Builder 的uploadDirectoryFollowSymbolicLinks(...)解析逻辑见 TransferManagerConfiguration.resolveUploadDirectoryFollowSymbolicLinks。四、单对象传输4.1 上传文件到 S3 并监听进度需要提供源文件路径和一个指定目标 bucket/key 的PutObjectRequest可选地挂载TransferListener监控进度。README 示例S3TransferManager transferManager S3TransferManager.create(); UploadFileRequest uploadFileRequest UploadFileRequest.builder() .putObjectRequest(req - req.bucket(bucket).key(key)) // attaching a LoggingTransferListener that will log the progress .addTransferListener(LoggingTransferListener.create()) .source(Paths.get(myFile.txt)) .build(); FileUpload upload transferManager.uploadFile(uploadFileRequest); // Wait for the transfer to complete upload.completionFuture().join();请求模型 UploadFileRequest 只持有三个字段putObjectRequest、sourcePath也可传File自动转换和transferListeners列表。注意 Javadoc 提示源文件在重试时可能被完整读取多次且文件不存在或无读权限时会抛异常。对于非文件场景如上传内存中的字节流可以改用upload(UploadRequest)请求体为AsyncRequestBodyUploadRequest uploadRequest UploadRequest.builder() .requestBody(AsyncRequestBody.fromString(Hello world)) .putObjectRequest(req - req.bucket(bucket).key(key)) .build(); Upload upload transferManager.upload(uploadRequest); upload.completionFuture().join();4.2 从 S3 下载对象到本地文件S3TransferManager transferManager S3TransferManager.create(); DownloadFileRequest downloadFileRequest DownloadFileRequest.builder() .getObjectRequest(req - req.bucket(bucket).key(key)) .destination(Paths.get(myFile.txt)) // attaching a LoggingTransferListener that will log the progress .addTransferListener(LoggingTransferListener.create()) .build(); FileDownload download transferManager.downloadFile(downloadFileRequest); // Wait for the transfer to complete download.completionFuture().join();接口 Javadoc 补充了文件处理语义S3TransferManager.downloadFile目标文件不存在则创建权限取决于文件系统/平台已存在则替换出错时 SDK 不会删除已写入的文件会保留原样由你自己处理。同样存在非文件版本download(DownloadRequest)通过AsyncResponseTransformer决定响应落地方式。官方示例把整个对象读入内存AsyncResponseTransformer.toBytes()Javadoc 明确警告该用法不适合大对象实际项目通常使用toFile(...)等 transformer。4.3 在 S3 内部复制对象S3TransferManager transferManager S3TransferManager.create(); CopyObjectRequest copyObjectRequest CopyObjectRequest.builder() .sourceBucket(source_bucket) .sourceKey(source_key) .destinationBucket(dest_bucket) .destinationKey(dest_key) .build(); CopyRequest copyRequest CopyRequest.builder() .copyObjectRequest(copyObjectRequest) .build(); Copy copy transferManager.copy(copyRequest); // Wait for the transfer to complete CompletedCopy completedCopy copy.completionFuture().join();copy的 Javadoc 中有三点值得注意S3TransferManager.copy智能分片复制根据底层客户端能力小对象走普通CopyObjectRequest大对象走并行的UploadPartCopyRequest分片复制CRT 客户端下可通过minimumPartSizeInBytes调节元数据默认随对象复制如需自定义需在CopyObjectRequest中设置metadata(...)并将metadataDirective(...)设为REPLACE进度回调受限由于 S3 在服务端完成字节复制TransferListener收不到bytesTransferred回调只有完成/失败事件。跨区域复制时需要在 CRT 客户端上开启crossRegionAccessEnabled(true)再交给 Transfer Manager。五、进度监听TransferListener 机制README 中的示例使用了LoggingTransferListener而接口 TransferListener.java 定义了完整的事件契约四个回调均为 default 方法按需实现即可回调触发时机上下文可获取的信息transferInitiated每次传输恰好一次request()、progressSnapshot()bytesTransferred每提交/收到一段字节可能调用很多次request()、progressSnapshot()transferComplete成功完成时恰好一次request()、progressSnapshot()、completedTransfer()transferFailed失败时恰好一次request()、progressSnapshot()、exception()失败场景下transferInitiated与transferFailed各调用一次其余回调无保证。progressSnapshot()提供transferredBytes()、ratioTransferred()等进度查询方法。Javadoc 同时列出了必须遵守的使用规则回调不得阻塞调用线程耗时操作要自行调度到别的线程bytesTransferred调用频率很高取决于 I/O buffer 大小副作用操作要考虑限流回调可能来自不同线程有状态的监听器必须线程安全监听器不能用于控制流实现中不应抛异常——抛出的异常会被抑制并记录为错误日志。内置的 LoggingTransferListener 是一个现成的参考实现它按 INFO 级别打印进度条通过maxTicks默认 20 格即每前进 5% 才打一行日志对输出做了限流create()用默认配置create(int maxTicks)可自定义格数。成功传输的日志效果类似Transfer initiated... | | 0.0% | | 12.5% | | 25.0% ... || 100.0% Transfer complete!另外两条 Javadoc 中说明的进度语义细节单部分内存上传的进度是在全部字节发送并收到 HTTP 响应后一次性上报的单部分文件上传的进度是按从文件读出字节上报的所以 100% 与最终完成之间会有延迟分片上传还需额外执行CompleteMultipartUpload。六、暂停与恢复Pause ResumeREADME 概览中提到pause the transfer for execution at a later time具体 API 是FileUpload#pause()与S3TransferManager#resumeUploadFile(...)下载侧对称。仓库中的示例代码S3TransferManagerSamples.java给出了完整流程S3TransferManager transferManager S3TransferManager.create(); UploadFileRequest uploadFileRequest UploadFileRequest.builder() .putObjectRequest(req - req.bucket(bucket).key(key)) .source(Paths.get(myFile.txt)) .build(); // Initiate the transfer FileUpload upload transferManager.uploadFile(uploadFileRequest); // Pause the upload ResumableFileUpload resumableFileUpload upload.pause(); // Optionally, persist the resumableFileUpload Path path Paths.get(resumableFileUpload.json); resumableFileUpload.serializeToFile(path); // Retrieve the resumableFileUpload from the file ResumableFileUpload persistedResumableFileUpload ResumableFileUpload.fromFile(path); // Resume the upload FileUpload resumedUpload transferManager.resumeUploadFile(persistedResumableFileUpload); // Wait for the transfer to complete resumedUpload.completionFuture().join();要点解析pause()返回一个 ResumableFileUpload 状态对象内部保存uploadFileRequest、fileLastModified、multipartUploadId、partSizeInBytes、totalParts、fileLength、transferredParts——恢复时正是靠multipartUploadId 已传分片数跳过已上传部分只上传剩余数据状态对象支持serializeToFile(path)/ResumableFileUpload.fromFile(path)持久化为 JSON可跨进程恢复序列化器见 internal/serialization 目录注意序列化时TransferRequestOverrideConfiguration和PutObjectRequest里的AwsRequestOverrideConfiguration不会被保留一致性校验若恢复时发现源文件自暂停后被修改过fileLastModified/fileLength变化SDK 会当作全新的UploadFileRequest从头上传接口 Javadoc 明确说明了这一行为分片上传/下载能力的断点续传有专门的测试覆盖如 S3TransferManagerUploadPauseResumeIntegrationTest.java 与 S3TransferManagerDownloadPauseResumeIntegrationTest.java。此外还有预签名 URL 下载入口downloadFileWithPresignedUrl(...)/downloadWithPresignedUrl(...)见 S3TransferManager.java在 CRT 或 multipart 客户端下同样支持分片下载但 Javadoc 明确注明其结果不支持暂停/恢复。七、目录级批量传输7.1 递归上传本地目录README 示例S3TransferManager transferManager S3TransferManager.create(); DirectoryUpload directoryUpload transferManager.uploadDirectory(UploadDirectoryRequest.builder() .sourceDirectory(Paths.get(source/directory)) .bucket(bucket) .build()); // Wait for the transfer to complete CompletedDirectoryUpload completedDirectoryUpload directoryUpload.completionFuture().join(); // Print out any failed uploads completedDirectoryUpload.failedTransfers().forEach(System.out::println);注意源码中UploadDirectoryRequest的字段名是source(Path)见 UploadDirectoryRequest.java 的 Builder 定义README 中写作sourceDirectory时请以当前源码为准。该请求的完整可配置项Builder 方法说明source(Path)要上传的本地源目录bucket(String)目标 S3 buckets3Prefix(String)S3 键名前缀默认空字符串s3Delimiter(String)键名分隔符默认/followSymbolicLinks(Boolean)是否跟随符号链接默认false请求级配置优先于 Builder 级maxDepth(Integer)遍历的最大目录层数1表示仅上传源目录直接包含的文件uploadFileRequestTransformer(Consumer)对每个文件上传请求做统一改写如统一附加标签键名映射规则与目录结构示例源自接口 JavadocS3TransferManager.uploadDirectory本地目录/test下为sample.jpg、photos/2022/January/sample.jpg、photos/2022/February/sample1..3.jpg上传后 bucket 中生成sample.jpg、photos/2022/January/sample.jpg、photos/2022/February/sample1.jpg等对象子目录被递归展开。必须关注的语义返回的CompletableFuture只在请求整体无法执行如源目录不存在时才异常完成部分文件失败时 future 仍是成功完成因此即使 future 成功也要检查CompletedDirectoryUpload#failedTransfers()。7.2 从 S3 下载整个前缀下的目录README 示例S3TransferManager transferManager S3TransferManager.create(); DirectoryDownload directoryDownload transferManager.downloadDirectory( DownloadDirectoryRequest.builder() .destination(Paths.get(destination/directory)) .bucket(bucket) // only download objects with prefix photos .listObjectsV2RequestTransformer(l - l.prefix(photos)) .build()); // Wait for the transfer to complete CompletedDirectoryDownload completedDirectoryDownload directoryDownload.completionFuture().join(); // Print out any failed downloads completedDirectoryDownload.failedTransfers().forEach(System.out::println);默认会下载 bucket 中全部对象通过listObjectsV2RequestTransformer(...)示例中限定prefix(photos)或filter(...)一个 DownloadFilter 谓词缩小下载范围。下载的目录结构与 S3 键结构一一对应Javadoc 给出了与 7.1 对称的示例。目标目录不存在时 SDK 会自动创建同名文件已存在时内容会被替换。同样地future成功完成不代表零失败务必检查failedTransfers()。目录操作的并发度由 Builder 的transferDirectoryMaxConcurrency(...)控制默认 100文件树遍历任务则跑在executor(...)指定的线程池上。八、源码结构与测试布局速览关注点位置公开接口与 Javadoc 示例S3TransferManager.java客户端选择与工厂internal/TransferManagerFactory.java默认配置/线程池internal/TransferManagerConfiguration.javaCRT 客户端实现internal/CrtS3TransferManager.java泛型客户端实现internal/GenericS3TransferManager.java请求/结果模型model 包UploadFileRequest、DownloadFileRequest、CopyRequest、ResumableFileUpload等进度监听progress 包TransferListener、LoggingTransferListener单元/集成测试src/test 与 src/it覆盖上传、下载、复制、目录、暂停恢复、预签名 URL 等场景Javadoc 引用的代码片段S3TransferManagerSamples.java九、实践建议小结大文件/高吞吐场景显式用S3AsyncClient.crtBuilder()并按网络能力设置targetThroughputInGbps与minimumPartSizeInBytes注意MB常量这是 README 推荐的默认姿势进度条直接挂LoggingTransferListener.create()即可获得每 5% 一行的限流日志自定义监听器务必非阻塞、线程安全、不抛异常长时任务上传/下载前先pause()并把ResumableFileUpload/ResumableFileDownload序列化到文件进程重启后resume...File续传源文件改动会导致整文件重传属于设计行为目录操作始终检查failedTransfers()用s3Prefix/maxDepth/listObjectsV2RequestTransformer精确控制传输范围用transferDirectoryMaxConcurrency调并发资源管理Transfer Manager 实现了SdkAutoCloseable使用完毕后close()但外部注入的S3AsyncClient与Executor需要你自己关闭。【免费下载链接】aws-sdk-java-v2The official AWS SDK for Java - Version 2项目地址: https://gitcode.com/GitHub_Trending/aw/aws-sdk-java-v2创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考