Theo document của laravel thì trước khi sử dụng S3 driver cần cài đặt packge league/flysystem-aws-s3-v3 ~1.0
thông qua composer
composer require league/flysystem-aws-s3-v3
AWS_ACCESS_KEY_ID=
AWS_SECRET_ACCESS_KEY=
AWS_DEFAULT_REGION=
AWS_BUCKET=
Viết một MediaTrait để xử lý việc upload file lên s3
<?php
namespace App\Traits;
use App\Helpers\Common;
use App\Helpers\Constants;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Facades\Log;
use Carbon\Carbon;
use Exception;
trait MediaTrait
{
/**
* Upload file role private.
*
* @param object $file
* @param string $path
* @param boolean $isRename
*
* @return boolean|string
*/
public function uploadImage(object $file, string $path, bool $isRename = true)
{
try {
$fileName = $this->getFileName($file, $isRename);
$key = $this->getUploadKey($path, $fileName);
Storage::disk('s3')->put($key, file_get_contents($file));
return $fileName;
} catch (Exception $e) {
Log::error('[ERROR_S3_UPLOAD_IMAGE] =>' . $e->getMessage());
return false;
}
}
/**
* Get file name.
*
* @param object $file
* @param boolean $isRename
*
* @return string
*/
public function getFileName(object $file, bool $isRename = true): string
{
$fileName = $file->getClientOriginalName();
// Check file upload by blob
if ($fileName === Constants::FILE_BLOB) {
return Common::encryptFileName(
Common::generateUuid(),
Constants::DEFAULT_EXT_FILE_BLOB
);
}
if ($isRename) {
$fileName = Common::encryptFileName(
Common::generateUuid(),
$file->getClientOriginalExtension()
);
}
return $fileName;
}
/**
* Gennerate presigned url has expried time.
*
* @param string $name
* @param string $path
*
* @return null|string
*/
public function getUrl(string $name, string $path)
{
try {
return Storage::disk('s3')->temporaryUrl(
$this->getUploadKey($path, $name),
Carbon::now()->addMinutes(config('filesystems.disks.s3.time_presigned_url'))
);
} catch (Exception $e) {
Log::error('ERROR_S3_GET_URL:' . $e->getMessage());
return null;
}
}
/**
* Delete image.
*
* @param string $name
* @param string $path
*
* @return boolean
*/
public function deleteImage(string $name, string $path): bool
{
try {
$key = $this->getUploadKey($path, $name);
return Storage::disk('s3')->delete($key);
} catch (Exception $e) {
Log::error('[ERROR_S3_DELETE_IMAGE] =>' . $e->getMessage());
return false;
}
}
/**
* Get upload key to s3.
*
* @param string $path path.
* @param string $name name.
*
* @return string
*/
public function getUploadKey(string $path, string $name): string
{
return sprintf('%s/%s', $path, $name);
}
/**
* Create s3 pre-signed url.
*
* @param string $name
* @param string $path
* @return null|string
*/
public function getPutObjectUrl(string $name, string $path): string
{
$filePath = $this->getUploadKey($path, $name);
$adapter = Storage::disk('s3')->getAdapter();
$client = $adapter->getClient();
$bucket = $adapter->getBucket();
$cmd = $client->getCommand('PutObject', [
'Bucket' => $bucket,
'Key' => $adapter->getPathPrefix() . $filePath
]);
$request = $client->createPresignedRequest($cmd, '+5 minutes');
return (string)$request->getUri();
}
}
khi dùng để upload file ở contrller chỉ việc user MediaTrait vào là có thể dùng được ngay, không phải viết lại constuctor như cách 2 sử dụng ở các phiên bản cũ.
Chú ý nếu đùng minio thì cần thêm config trong file config/filesystems.php
use_path_style_endpoint => true
Sử dụng tinker để test thử xem có upload được file lên s3 hay không
// truy cập vào tinker
php artisan tinker
// Use storage
use Illuminate\Support\Facades\Storage;
// Upload file to s3
Storage::disk('s3')->put($s3Path, $content);
vd: Storage::disk('s3')->put('test.txt', 'hello');
// Get all file trên s3
Storage::disk('s3')->allFiles();
// Tạo 1 url tạm để download, xem file từ s3
Storage::disk('s3')->temporaryUrl($s3Path, now()->addMinutes(20));
Nếu bạn sử dụng phiên bản laravel cũ nhỏ hơn 5.7 thì đọc bài viết link bên dưới này nhé