亚马逊s3是否支持批量上传? 我有一份工作需要每晚上传~100K的文件,最高可达1G但是偏向于小文件(90%小于100字节,99%小于1000字节)。
s3 API是否支持在单个HTTP调用中上传多个对象?
所有对象必须在S3中作为单个对象可用。我无法在其他任何地方(FTP等)或其他格式(数据库,EC2本地驱动器等)托管它们。这是我无法改变的外部要求。
答案 0 :(得分:40)
答案 1 :(得分:30)
s3 API是否支持在单个HTTP调用中上传多个对象?
不,the S3 PUT operation仅支持每个HTTP请求上传一个对象。
您可以在计算机上安装要与远程存储桶同步的S3 Tools,然后运行以下命令:
s3cmd sync localdirectory s3://bucket/
然后,您可以将此命令放在脚本中,并创建一个计划作业,以便每晚运行此命令。
这应该做你想要的。
该工具基于MD5哈希值和文件大小执行文件同步,因此碰撞应该很少(如果您真的希望可以使用“s3cmd put”命令强制盲目覆盖目标存储桶中的对象)。
编辑:另外请确保您阅读了我为S3 Tools链接的网站上的文档 - 您是否希望从本地删除文件或忽略等文件所需的不同标志。
答案 2 :(得分:1)
要补充每个人所说的话,如果您希望Java代码(而不是CLI)执行此操作而不必将所有文件放在单个目录中,则可以创建要上传的文件列表,并然后将该列表提供给AWS TransferManager的uploadFileList方法。
答案 3 :(得分:1)
这是一个全面的批处理解决方案,可以使用一次CommandPool::batch调用将文件从一个文件夹复制到另一个文件夹,尽管在幕后它为每个文件运行一个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();
}
}
答案 4 :(得分:0)
一个文件(或文件的一部分)=一个HTTP请求,但Java API现在支持高效的多文件上载,而无需使用TransferManager
自行编写多线程答案 5 :(得分:0)
如果您想使用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();
答案 6 :(得分:0)
是否可以批量上传到 Amazon S3?
是*。
<块引用>S3 API 是否支持在单个 HTTP 调用中上传多个对象?
没有
Amazon S3 API 不支持批量上传,但 awscli 支持并发(并行)上传。从客户端的角度和带宽效率来看,这些选项的执行方式应该大致相同。
────────────────────── 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
how can I improve the transfer performance of the sync command for Amazon S3? 上的文档建议通过两种方式增加并发性。其中之一是这样的:
<块引用>为了潜在地提高性能,您可以修改 max_concurrent_requests
的值。此值设置一次可以发送到 Amazon S3 的请求数。默认值为 10,您可以将其增加到更高的值。但是,请注意以下几点:
--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。下图显示了上传 aws
进程的 CPU 使用率、RSS 和线程数。