是否可以执行批量上传到 Amazons3?

亚马逊 s3支持批量上传吗? 我的工作需要每晚上传大约100K 的文件,最大可以达到1G,但是偏向于小文件(90% 的文件小于100字节,99% 的文件小于1000字节)。

S3API 是否支持在一个 HTTP 调用中上传多个对象?

所有对象必须在 S3中作为单独的对象可用。我无法在其他地方(FTP 等)或其他格式(数据库、 EC2本地驱动器等)托管它们。这是我无法改变的外部要求。

87859 次浏览

S3API 是否支持在一个 HTTP 调用中上传多个对象?

不,S3PUT 操作只支持每个 HTTP 请求上传一个对象。

您可以在计算机上安装要与远程 bucket 同步的 中三工具,然后运行以下命令:

s3cmd sync localdirectory s3://bucket/

然后,您可以将此命令放在一个脚本中,并创建一个计划作业,以便每晚运行此命令。

这应该是你想要的。

该工具执行基于 MD5哈希和文件大小的档案同步,所以碰撞应该是罕见的(如果你真的想要,你可以使用“ s3cmd put”命令来强制盲覆盖目标桶中的对象)。

编辑: 还要确保您阅读了我为 S3 Tools 链接的站点上的文档——对于您是希望将本地删除的文件从 bucket 中删除还是忽略等,有不同的标记需要使用。

或者,您可以使用 同步命令通过 AWS CLI 工具上载 S3。

Aws s3 sync Local _ file 本地 _ 文件夹 s3://bucket-name

您可以使用这种方法批量上传文件到 S3非常快。

一个文件(或文件的一部分) = 一个 HTTP 请求,但是 Java API 现在支持有效的多文件上传,而无需使用 转帐经理自己编写多线程

如果你想使用 Java 程序,你可以这样做:

public  void uploadFolder(String bucket, String path, boolean includeSubDirectories) {
File dir = new File(path);
MultipleFileUpload upload = transferManager.uploadDirectory(bucket, "", dir, includeSubDirectories);
try {
upload.waitForCompletion();
} catch (InterruptedException e) {
e.printStackTrace();
}
}

创建 s3client 和传输管理器以连接到本地 S3(如果您希望测试)如下:

    AWSCredentials credentials = new BasicAWSCredentials(accessKey, token);
s3Client = new AmazonS3Client(credentials); // This is deprecated but you can create using standard beans provided by spring/aws
s3Client.setEndpoint("http://127.0.0.1:9000");//If you wish to connect to local S3 using minio etc...
TransferManager transferManager = TransferManagerBuilder.standard().withS3Client(s3Client).build();

如果你想让你的 Java 代码(而不是 CLI)在不需要把所有文件放在一个目录中的情况下做到这一点,你可以创建一个文件上传列表,然后将这个列表提供给 AWS TransferManager 的 uploadFileList 方法。

Https://docs.aws.amazon.com/awsjavasdk/latest/javadoc/com/amazonaws/services/s3/transfer/transfermanager.html#uploadfilelist-java.lang . String-java. lang. String-java.io. File-java. util. List-

下面是一个全面的批处理解决方案,它使用一个单独的 命令池: : 批处理调用将文件从一个文件夹复制到另一个文件夹,尽管在底层它对每个文件运行一个 ExecuteAsync 执行异步命令,不确定它是否算作一个单独的 API 调用。据我所知,您应该能够使用这种方法复制数十万个文件,因为没有办法将批处理发送到 AWS 进行处理。

安装 SDK:

composer require aws/aws-sdk-php
use Aws\ResultInterface;
use Aws\S3\S3Client;
use Aws\S3\Exception\S3Exception;
use Aws\S3\Exception\DeleteMultipleObjectsException;


$bucket = 'my-bucket-name';


// Setup your credentials in the .aws folder
// See: https://docs.aws.amazon.com/sdk-for-php/v3/developer-guide/guide_credentials_profiles.html
$s3 = new S3Client([
'profile' => 'default',
'region'  => 'us-east-2',
'version' => 'latest'
]);


// Get all files in S3
$files = array();
try {
$results = $s3->getPaginator('ListObjects', [
'Bucket' => $bucket,
'Prefix' => 'existing-folder' // Folder within bucket, or remove this to get all files in the bucket
]);


foreach ($results as $result) {
foreach ($result['Contents'] as $object) {
$files[] = $object['Key'];
}
}
} catch (AwsException $e) {
error_log($e->getMessage());
}


if(count($files) > 0){
// Perform a batch of CopyObject operations.
$batch = [];
foreach ($files as $file) {
$batch[] = $s3->getCommand('CopyObject', array(
'Bucket'     => $bucket,
'Key'        => str_replace('existing-folder/', 'new-folder/', $file),
'CopySource' => $bucket . '/' . $file,
));
}


try {
$results = CommandPool::batch($s3, $batch);


// Check if all files were copied in order to safely delete the old directory
$count = 0;
foreach($results as $result) {
if ($result instanceof ResultInterface) {
$count++;
}
if ($result instanceof AwsException) {
}
}


if($count === count($files)){
// Delete old directory
try {
$s3->deleteMatchingObjects(
$bucket, // Bucket
'existing-folder' // Prefix, folder within bucket, as indicated above
);
} catch (DeleteMultipleObjectsException $exception) {
return false;
}


return true;
}


return false;


} catch (AwsException $e) {
return $e->getMessage();
}
}

调查

是否可以执行批量上传到 AmazonS3?

是的。

S3API 是否支持在一个 HTTP 调用中上传多个对象?

没有。

解释

AmazonS3API 不支持批量上传,但 (咒语)支持并发(并行)上传。从客户端的角度和带宽效率来看,这些选项的执行方式大致相同。

 ────────────────────── time ────────────────────►


1. Serial
------------------
POST /resource
────────────────► POST /resource
payload_1     └───────────────► POST /resource
payload_2     └───────────────►
payload_3
2. Bulk
------------------
POST /bulk
┌────────────┐
│resources:  │
│- payload_1 │
│- payload_2 ├──►
│- payload_3 │
└────────────┘


3. Concurrent
------------------
POST /resource
────────────────►
payload_1


POST /resource
────────────────►
payload_2


POST /resource
────────────────►
payload_3

命令行接口

关于 如何提高 AmazonS3的 sync 命令的传输性能?的文档建议通过两种方式提高并发性,其中之一是:

要潜在地提高性能,可以修改 max_concurrent_requests的值。此值设置一次可以发送到 AmazonS3的请求数。默认值为10,可以将其增加到更高的值。不过,请注意以下事项:

  • 运行更多的线程会在计算机上消耗更多的资源。您必须确保您的计算机有足够的资源来支持所需的最大并发请求数。
  • 太多的并发请求会使系统不堪重负,这可能会导致连接超时或降低系统的响应速度。为了避免来自 AWS CLI 的超时问题,可以尝试将 --cli-read-timeout值或 --cli-connect-timeout值设置为0。

设置 max_concurrent_requests并上传目录的脚本如下所示:

aws configure set s3.max_concurrent_requests 64
aws s3 cp local_path_from s3://remote_path_to --recursive

为了提供有关 运行更多的线程会消耗更多的资源的线索,我在运行 aws-cli的容器中(使用 procpath)进行了一个小测量,将包含约550个 HTML 文件(总共约40 MiB,平均文件大小约72 KiB)的目录上传到 S3。下图显示了 CPU 使用率、 RSS 和上传 aws进程的线程数。

aws s3 cp --recursive, max_concurrent_requests=64