Làm thế nào để upload file từ local server lên S3 compatible storage bằng ngôn ngữ PHP
Upload file lên S3
Để tải tệp lên S3 thông qua API, bạn có thể sử dụng AWS SDK cho PHP. Dưới đây là ví dụ cách tải tệp lên S3 bằng PHP và sử dụng AWS SDK for PHP.
Cài đặt SDK
composer require aws/aws-sdk-php
Cấu hình tài khoản AWS
use Aws\S3\S3Client;
$s3 = new S3Client([
'version' => 'latest',
'region' => 'region-name',
'credentials' => [
'key' => 'ACCESS_KEY',
'secret' => 'SECRET_KEY',
],
]);
Trong đó region-name, ACCESS_KEY, và SECRET_KEY là thông tin xác thực tài khoản AWS của bạn.
Tải file lên S3
use Aws\S3\Exception\S3Exception;
try {
$s3->putObject([
'Bucket' => 'bucket-name',
'Key' => 'object-name',
'SourceFile' => 'path/to/local/file',
]);
} catch (S3Exception $e) {
echo $e->getMessage() . "\n";
}
Trong đó:
- "bucket-name": tên bucket S3 mà bạn muốn tải tệp lên.
- "object-name": tên đối tượng mà bạn muốn đặt cho tệp trên S3.
- "path/to/local/file": đường dẫn đến tệp cần tải lên.
Bạn có thể thay đổi tên bucket và tên đối tượng theo ý của mình. Bây giờ file của bạn đã được tải lên S3.
Vậy để tải nhiều file lên hàng loạt thì phải làm sao?
Để tải lên hàng loạt files lên Amazon S3 bằng PHP thông qua API, bạn có thể sử dụng các phương thức trong AWS SDK để lặp lại các yêu cầu tải lên cho mỗi tệp. Dưới đây là một ví dụ về cách tải lên hàng loạt tệp bằng PHP và sử dụng AWS SDK for PHP.
use Aws\S3\S3Client;
use Aws\Exception\AwsException;
$bucketName = 'BUCKET_NAME';
$localDirectory = 'LOCAL_DIRECTORY';
$s3Directory = 'S3_DIRECTORY';
$s3 = new S3Client([
'version' => 'latest',
'region' => 'REGION_NAME',
'credentials' => [
'key' => 'ACCESS_KEY',
'secret' => 'SECRET_KEY',
],
]);
try {
$iterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($localDirectory));
foreach ($iterator as $file) {
if ($file->isFile()) {
$relativePath = substr($file->getPathname(), strlen($localDirectory) + 1);
$s3Path = $s3Directory . '/' . str_replace('\\', '/', $relativePath);
$s3->putObject([
'Bucket' => $bucketName,
'Key' => $s3Path,
'SourceFile' => $file->getPathname(),
]);
echo 'File ' . $file->getPathname() . ' uploaded to S3 ' . $bucketName . '/' . $s3Path . PHP_EOL;
}
}
} catch (AwsException $e) {
echo $e->getMessage();
}
Trong đó:
BUCKET_NAME
là tên bucket S3 mà bạn muốn tải các tệp lên.LOCAL_DIRECTORY
là thư mục chứa các tệp cần tải lên.S3_DIRECTORY
là thư mục trên S3 mà bạn muốn lưu các tệp lên.REGION_NAME, ACCESS_KEY và SECRET_KEY
là thông tin xác thực tài khoản AWS của bạn.
Đoạn code này sử dụng đối tượngRecursiveIteratorIterator
để lặp lại tất cả các tệp trong thư mụcLOCAL_DIRECTORY
, sau đó đối tượngS3Client
để tải lên từng tệp lên bucket S3. Bằng cách lặp lại yêu cầu tải lên cho mỗi tệp, đoạn code sẽ tải lên hàng loạt các tệp vào bucket S3.
Vậy để tối ưu đoạn code trên tránh tình trạng bị timeout thì phải làm sao?
Để giải quyết vấn đề này, bạn có thể sử dụng một số thư viện PHP hỗ trợ cho việc tải lên hàng loạt các tệp tin đồng bộ và bất đồng bộ. Một trong số đó là thư viện "spatie/async" (https://github.com/spatie/async), cho phép tải lên hàng loạt các tệp tin theo chế độ bất đồng bộ và quản lý tải lên các tệp tin theo hàng đợi.
Để sử dụng thư viện "spatie/async", bạn cần cài đặt nó bằng Composer:
composer require spatie/async
Sau đó, bạn có thể sử dụng đoạn code sau để tải lên hàng loạt các tệp tin và cho phép chỉ tải lên tối đa 3 tệp tin cùng một lúc:
use Spatie\Async\Pool;
$pool = Pool::create();
$localPath = '/path/to/local/files';
$bucketName = 'my-bucket';
$files = scandir($localPath);
foreach ($files as $file) {
if (in_array($file, ['.', '..'])) {
continue;
}
$pool->add(function () use ($s3Client, $localPath, $file, $bucketName) {
$s3Client->putObject([
'Bucket' => $bucketName,
'Key' => basename($file),
'SourceFile' => $localPath . '/' . $file,
]);
})->then(function () use ($file) {
echo "File $file uploaded successfully.\n";
});
if ($pool->countActive() >= 3) {
$pool->wait();
}
}
$pool->wait();
Đoạn code trên sử dụng phương thức scandir
để lấy danh sách tệp tin trong thư mục $localPath
. Sau đó, với mỗi tệp tin, nó sử dụng phương thức add
để thêm một công việc mới vào hàng đợi.
Phương thức add
trả về một đối tượng Promise
đại diện cho kết quả của công việc đó. Sau khi thêm một công việc vào hàng đợi, nó kiểm tra số lượng công việc đang hoạt động (được xác định bởi phương thức countActive
) và nếu nó đạt tối đa (trong trường hợp này là 3), nó gọi phương thức wait
để đợi cho tất cả các công việc đang hoạt động hoàn thành trước khi tiếp tục thêm công việc vào hàng đợi.
Điều này giúp bạn kiểm soát lượng tệp tin đang được tải lên cùng một lúc và tránh tình trạng quá tải tài nguyên của máy chủ và giảm thiểu tình trạng trễ trong quá trình tải lên. Khi tất cả các công việc được thêm vào hàng đợi, nó gọi phương thức wait
để chờ tất cả các công việc hoàn thành trước khi kết thúc.
Nếu bạn muốn tải lên các tệp tin trong một thời gian nhất định, bạn có thể sử dụng một biến thời gian (ví dụ: $timeToRun
) và kiểm tra xem thời gian đã trôi qua chưa. Ví dụ, bạn có thể sửa đoạn code trên như sau:
use Spatie\Async\Pool;
$pool = Pool::create();
$localPath = '/path/to/local/files';
$bucketName = 'my-bucket';
$files = scandir($localPath);
$timeToRun = time() + 60; // Run for 60 seconds
foreach ($files as $file) {
if (in_array($file, ['.', '..'])) {
continue;
}
$pool->add(function () use ($s3Client, $localPath, $file, $bucketName) {
$s3Client->putObject([
'Bucket' => $bucketName,
'Key' => basename($file),
'SourceFile' => $localPath . '/' . $file,
]);
})->then(function () use ($file) {
echo "File $file uploaded successfully.\n";
});
if ($pool->countActive() >= 3) {
$pool->wait();
}
if (time() >= $timeToRun) {
break;
}
}
$pool->wait();
Trong đoạn code này, biến $timeToRun
được sử dụng để đặt thời gian tối đa để tải lên các tệp tin là 60 giây.
Trong vòng lặp, sau khi thêm một công việc vào hàng đợi, nó kiểm tra xem thời gian đã trôi qua chưa bằng cách sử dụng hàm time
.
Nếu thời gian đã trôi qua, nó sẽ thoát khỏi vòng lặp. Sau đó, nó gọi phương thức wait
để chờ tất cả các công việc hoàn thành trước khi kết thúc.
Với cách tiếp cận này, bạn có thể quản lý tải lên hàng loạt các tệp tin một cách hiệu quả và tránh tình trạng quá tải tài nguyên của máy chủ.