العمل مع S3 والتخزين السحابي في Kotlin
\n\nفي التطوير الحديث باستخدام Kotlin، غالبًا ما تنشأ الحاجة إلى التكامل مع التخزين السحابي المتوافق مع بروتوكول Amazon S3 (Simple Storage Service). يمكن أن يكون ذلك AWS S3، MinIO، DigitalOcean Spaces، Yandex Object Storage وغيرها. في هذه المقالة، سننظر في نهجين رئيسيين: استخدام AWS SDK الرسمي لـ Kotlin وعميل خفيف الوزن يعتمد على Ktor.
\n\n1. AWS SDK لـ Kotlin (aws-sdk-kotlin)
\n\nيوفر SDK الرسمي من Amazon واجهة برمجة تطبيقات (API) محددة النوع وغير متزامنة، تدعم بشكل كامل coroutines في Kotlin. هذا هو الحل الأكثر شمولاً للعمل مع S3.
\n\nإضافة التبعية
\nأضف إلى build.gradle.kts:
dependencies {\n implementation("aws.sdk.kotlin:s3:1.0.0")\n implementation("aws.smithy.kotlin:http-client-engine-ktor:1.0.0")\n}\n\nتهيئة العميل
\nimport aws.sdk.kotlin.services.s3.S3Client\nimport aws.sdk.kotlin.services.s3.model.*\n\nsuspend fun createClient(): S3Client = S3Client.fromEnvironment {\n region = "ru-central1"\n // لـ MinIO أو غيرها من التخزين المتوافق مع S3:\n endpointUrl = "https://storage.yandexcloud.net"\n // الإعداد عبر متغيرات البيئة AWS_ACCESS_KEY_ID و AWS_SECRET_ACCESS_KEY\n}\n\nرفع ملف (PutObject)
\nsuspend fun uploadFile(client: S3Client, bucket: String, key: String, filePath: String) {\n val fileBytes = java.io.File(filePath).readBytes()\n client.putObject(\n PutObjectRequest {\n this.bucket = bucket\n this.key = key\n this.body = fileBytes.toByteArray()\n }\n )\n println("تم رفع الملف $key إلى الحاوية $bucket")\n}\n\nتنزيل ملف (GetObject)
\nsuspend fun downloadFile(client: S3Client, bucket: String, key: String, savePath: String) {\n val response = client.getObject(\n GetObjectRequest {\n this.bucket = bucket\n this.key = key\n }\n )\n val bytes = response.body?.readAll()\n if (bytes != null) {\n java.io.File(savePath).writeBytes(bytes)\n println("تم حفظ الملف $key في $savePath")\n }\n}\n\nقائمة الكائنات في الحاوية
\nsuspend fun listObjects(client: S3Client, bucket: String): List<String> {\n val response = client.listObjectsV2(\n ListObjectsV2Request {\n this.bucket = bucket\n }\n )\n return response.contents?.map { it.key ?: "" } ?: emptyList()\n}\n\n2. Ktor S3 Client (بديل خفيف الوزن)
\n\nإذا كنت لا تحتاج إلى كل قوة AWS SDK، يمكنك استخدام Ktor مع مكتبة ktor-client-s3. هذا يوفر وزنًا أدنى وتحكمًا كاملاً في طلبات HTTP.
\n\nالإضافة
\ndependencies {\n implementation("io.ktor:ktor-client-core:2.3.0")\n implementation("io.ktor:ktor-client-cio:2.3.0")\n implementation("io.ktor:ktor-client-content-negotiation:2.3.0")\n implementation("io.ktor:ktor-serialization-kotlinx-json:2.3.0")\n // لتوقيع طلبات S3\n implementation("io.ktor:ktor-client-auth:2.3.0")\n}\n\nإنشاء عميل S3 باستخدام Ktor
\nimport io.ktor.client.*\nimport io.ktor.client.request.*\nimport io.ktor.client.statement.*\nimport io.ktor.http.*\nimport io.ktor.utils.io.*\n\nclass S3KtorClient(\n private val endpoint: String,\n private val accessKey: String,\n private val secretKey: String\n) {\n private val client = HttpClient {\n install(io.ktor.client.plugins.auth.Auth) {\n basic {\n credentials {\n username = accessKey\n password = secretKey\n }\n }\n }\n }\n\n suspend fun putObject(bucket: String, key: String, data: ByteArray) {\n client.put("