はじめに
始めまして.
この度はAdvent Calendar「Qiita学生iOS&Androidエンジニアのカレンダー」に誘われたので初めてQiitaに記事を書こうと思います.
minioとは
オンプレミスなAWS S3です.
minioの公式サイト
画像とか動画とかAPIで通信するには適さないなぁ〜
でもAWS契約するのもなぁ〜
自宅にサーバあるのになぁ〜
って人におすすめです.
今回は何を?
minioのサーバがあるとして,Androidでminioにデータ(CSVファイル)を送信してみようと思います
はじめよう
まずはGradleにminioの依存関係を書きましょう.
implementation 'io.minio:minio:8.5.1'
バージョンはその都度変えてください.
では,依存関係を書いたGradleです.
plugins {
id 'com.android.application'
id 'org.jetbrains.kotlin.android'
}
android {
namespace 'com.example.minio_client'
compileSdk 33
defaultConfig {
applicationId "com.example.minio_client"
minSdk 31
targetSdk 33
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = '1.8'
}
packagingOptions {
exclude 'javax/servlet/jsp/resources/jspxml.xsd'
exclude 'javax/servlet/jsp/resources/web-jsptaglibrary_2_0.xsd'
exclude 'javax/servlet/jsp/resources/web-jsptaglibrary_2_1.xsd'
exclude 'javax/servlet/http/LocalStrings_ja.properties'
exclude 'META-INF/mimetypes.default'
exclude 'javax/servlet/resources/web-app_2_4.xsd'
exclude 'javax/servlet/jsp/resources/web-jsptaglibrary_1_2.dtd'
exclude 'javax/servlet/resources/j2ee_web_services_client_1_1.xsd'
exclude 'javax/servlet/http/LocalStrings_fr.properties'
exclude 'javax/servlet/LocalStrings_ja.properties'
exclude 'javax/servlet/jsp/resources/web-jsptaglibrary_1_1.dtd'
exclude 'javax/servlet/http/LocalStrings_es.properties'
exclude 'javax/servlet/resources/xml.xsd'
exclude 'javax/servlet/http/LocalStrings.properties'
exclude 'javax/servlet/resources/XMLSchema.dtd'
exclude 'javax/servlet/resources/j2ee_web_services_1_1.xsd'
exclude 'javax/servlet/resources/web-app_2_2.dtd'
exclude 'javax/servlet/resources/j2ee_1_4.xsd'
exclude 'META-INF/DEPENDENCIES'
exclude 'javax/servlet/resources/web-app_2_5.xsd'
exclude 'javax/el/LocalStrings.properties'
exclude 'javax/servlet/jsp/resources/jspxml.dtd'
exclude 'javax/servlet/resources/datatypes.dtd'
exclude 'javax/servlet/jsp/resources/jsp_2_0.xsd'
exclude 'javax/servlet/LocalStrings_fr.properties'
exclude 'javax/servlet/LocalStrings.properties'
exclude 'javax/servlet/jsp/resources/jsp_2_1.xsd'
exclude 'javax/servlet/resources/web-app_2_3.dtd'
}
}
dependencies {
implementation 'androidx.core:core-ktx:1.9.0'
implementation 'androidx.appcompat:appcompat:1.6.0'
implementation 'com.google.android.material:material:1.8.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.5'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
implementation 'io.minio:minio:8.5.1'
implementation group: 'org.apache.openejb', name: 'javaee-api', version: '6.0-1'
implementation 'com.fasterxml.woodstox:woodstox-core:6.5.0'
}
あれ???すごく長くなっちゃった.
と,いうのも
僕が実装してみた時にライブラリ不足や競合が多く発生してしまい,それを解消したのがこちらです.
なぜこうなったのかを知りたい方はその時の苦悩がここにあるので見てください.
また,すでにある程度大きいプログラムで依存関係も複雑になってる場合これを実装すると競合が起こると思います.
僕はその時これで解消しました.
ではクライアントクラスを作ろう
package com.example.minio_client
import io.minio.MinioClient
import io.minio.UploadObjectArgs
class MinioClient {
val accessKey = "アクセスキー"
val secretKey = "シークレットキー"
val bucketName = "バケットの名前"
val endpoint = "https://~~~~"
fun postFile(pass: String): String {
val minioClient = MinioClient.builder()
.endpoint(endpoint)
.credentials(accessKey, secretKey)
.build()
// パスの後ろのファイル名をもらっておく
val fileName = pass.substringAfterLast("/")
try {
minioClient.uploadObject(
UploadObjectArgs.builder()
.bucket(bucketName)
// ファイルの名前."/"で区切ると階層を分けられる
.`object`("$fileName.csv")
// ファイルの場所
.filename(pass)
.build()
)
// 送信成功したらデータの場所を返してくれる
return "$endpoint/$bucketName/$fileName"
} catch (e: Exception) {
return "File upload failed: ${e.message}"
}
}
}
クラスを作ったのでActivityで読んであげましょう.
package com.example.minio_client
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val externalStorage = ExternalStorage(this)
val minioClient = MinioClient()
try {
val url = minioClient.postFile("CSVファイルの場所")
// あの関数はファイルの場所を返してくれる
Log.d("minio", "url = $url")
} catch (e: Exception) {
Log.d("minio", "error = ${e.message}")
}
}
}
おわりに
おそらくもっといいやり方があります.
当時は締め切りに追われて頭を焦がしながらこれを作りました.
もっといいやり方を知っている方や依存関係の問題を詳しく知っている人がいればコメントお願いします.