Skip to content

Commit

Permalink
Merge pull request #174 from Semoban/feature/fix_image_upload_logic
Browse files Browse the repository at this point in the history
  • Loading branch information
iiolo authored Apr 9, 2024
2 parents 380a2ff + 72b40c4 commit c2d9e25
Show file tree
Hide file tree
Showing 98 changed files with 1,414 additions and 1,143 deletions.
1 change: 1 addition & 0 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ android {
buildConfigField "String", "NAVER_OAUTH_CLIENT_SECRET", properties['naver_oauth_client_secret']
buildConfigField "String", "NAVER_OAUTH_CLIENT_NAME", properties['naver_oauth_client_name']
buildConfigField "String", "GOOGLE_CLIENT_ID", properties['google_client_id']
buildConfigField "String", "AWS_S3_BASE_URL", properties['aws_s3_base_url']
manifestPlaceholders["kakaoNativeAppKeyManifest"] = properties["kakao_native_app_key_manifest"] as String
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package com.project.meongcare.aws.model.data.remote

import com.project.meongcare.aws.model.entities.AWSS3Response
import okhttp3.RequestBody
import retrofit2.Response
import retrofit2.http.Body
import retrofit2.http.GET
import retrofit2.http.Header
import retrofit2.http.PUT
import retrofit2.http.Query
import retrofit2.http.Url

interface AWSS3Api {
@GET("aws/s3")
suspend fun getPreSignedUrl(
@Header("AccessToken") accessToken: String,
@Query("fileName") fileName: String,
): Response<AWSS3Response>

@PUT
suspend fun uploadImageToS3(
@Url preSignedUrl: String,
@Body image: RequestBody,
): Response<Int>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package com.project.meongcare.aws.model.data.remote

import com.project.meongcare.BuildConfig
import okhttp3.ResponseBody
import retrofit2.Converter
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
import java.lang.reflect.Type
import javax.inject.Inject

class AWSS3RetrofitClient
@Inject
constructor() {
val awsS3Api: AWSS3Api by lazy {
Retrofit.Builder()
.baseUrl(BuildConfig.SEMOBAN_DOMAIN)
.addConverterFactory(nullOnEmptyConverterFactory)
.addConverterFactory(GsonConverterFactory.create())
.build()
.create(AWSS3Api::class.java)
}

private val nullOnEmptyConverterFactory =
object : Converter.Factory() {
fun converterFactory() = this

override fun responseBodyConverter(
type: Type,
annotations: Array<out Annotation>,
retrofit: Retrofit,
) = object : Converter<ResponseBody, Any?> {
val nextResponseBodyConverter =
retrofit.nextResponseBodyConverter<Any?>(
converterFactory(),
type,
annotations,
)

override fun convert(value: ResponseBody) =
if (value.contentLength() != 0L) nextResponseBodyConverter.convert(value) else null
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.project.meongcare.aws.model.data.repository

import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent

@Module
@InstallIn(SingletonComponent::class)
object AWSS3Module {
@Provides
fun provideAWSS3Repository(awsS3RepositoryImpl: AWSS3RepositoryImpl): AWSS3Repository {
return awsS3RepositoryImpl
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.project.meongcare.aws.model.data.repository

import com.project.meongcare.aws.model.entities.AWSS3Response
import okhttp3.RequestBody

interface AWSS3Repository {
suspend fun getPreSignedUrl(
accessToken: String,
fileName: String,
): AWSS3Response?

suspend fun uploadImageToS3(
preSignedUrl: String,
image: RequestBody,
): Int?
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package com.project.meongcare.aws.model.data.repository

import android.util.Log
import com.project.meongcare.aws.model.data.remote.AWSS3RetrofitClient
import com.project.meongcare.aws.model.entities.AWSS3Response
import okhttp3.RequestBody
import org.json.JSONObject
import java.lang.Exception
import javax.inject.Inject

class AWSS3RepositoryImpl
@Inject
constructor(private val awsS3RetrofitClient: AWSS3RetrofitClient) : AWSS3Repository {
override suspend fun getPreSignedUrl(
accessToken: String,
fileName: String,
): AWSS3Response? {
return try {
val response = awsS3RetrofitClient.awsS3Api.getPreSignedUrl(accessToken, fileName)
if (response.isSuccessful) {
Log.d("AWSS3Repo-getPreUrl", "통신 성공 ${response.code()}")
response.body()
} else {
val stringToJson = JSONObject(response.errorBody()?.string()!!)
Log.e("AWSS3Repo-getPreUrl", "통신 실패 ${response.code()}\n$stringToJson")
null
}
} catch (e: Exception) {
e.printStackTrace()
null
}
}

override suspend fun uploadImageToS3(
preSignedUrl: String,
image: RequestBody,
): Int? {
return try {
val response = awsS3RetrofitClient.awsS3Api.uploadImageToS3(preSignedUrl, image)
if (response.isSuccessful) {
Log.d("AWSS3Repo-upload", "통신 성공 ${response.code()}")
response.code()
} else {
val stringToJson = JSONObject(response.errorBody()?.string()!!)
Log.e("AWSS3Repo-upload", "통신 실패 ${response.code()}\n$stringToJson")
response.code()
}
} catch (e: Exception) {
e.printStackTrace()
null
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package com.project.meongcare.aws.model.entities

data class AWSS3Response(
val preSignedUrl: String,
)
12 changes: 12 additions & 0 deletions app/src/main/java/com/project/meongcare/aws/util/AWSS3Constants.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.project.meongcare.aws.util

// Parent Folder
const val PARENT_FOLDER_PATH = "meongcare/"

// Sub Folder
const val DOG_FOLDER_PATH = "dog/"
const val EXCRETA_FOLDER_PATH = "excreta/"
const val FEED_FOLDER_PATH = "feed/"
const val MEDICAL_RECORD_FOLDER_PATH = "medical-record/"
const val MEMBER_FOLDER_PATH = "member/"
const val SUPPLEMENTS_FOLDER_PATH = "supplements/"
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package com.project.meongcare.aws.util

import android.content.Context
import android.net.Uri
import java.io.File
import java.io.FileOutputStream
import java.util.UUID

object AWSS3ImageUtils {
private fun createUUID(): String {
return UUID.randomUUID().toString()
}

fun convertUriToFile(
context: Context,
uri: Uri,
): File {
val contentResolver = context.contentResolver
val file = File(context.cacheDir, createUUID())
file.deleteOnExit()

contentResolver.openInputStream(uri).use { inputStream ->
FileOutputStream(file).use { outputStream ->
inputStream?.copyTo(outputStream)
}
}

return file
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package com.project.meongcare.aws.viewmodel

import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.project.meongcare.aws.model.data.repository.AWSS3Repository
import com.project.meongcare.aws.model.entities.AWSS3Response
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.launch
import okhttp3.RequestBody
import javax.inject.Inject

@HiltViewModel
class AWSS3ViewModel
@Inject
constructor(private val awsS3Repository: AWSS3Repository) : ViewModel() {
private val _preSignedUrl = MutableLiveData<AWSS3Response?>()
val preSignedUrl: LiveData<AWSS3Response?>
get() = _preSignedUrl

private val _uploadImageResponse = MutableLiveData<Int?>()
val uploadImageResponse: LiveData<Int?>
get() = _uploadImageResponse

fun getPreSignedUrl(
accessToken: String,
fileName: String,
) {
viewModelScope.launch {
_preSignedUrl.value = awsS3Repository.getPreSignedUrl(accessToken, fileName)
}
}

fun uploadImageToS3(
preSignedUrl: String,
image: RequestBody,
) {
viewModelScope.launch {
_uploadImageResponse.value = awsS3Repository.uploadImageToS3(preSignedUrl, image)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@ package com.project.meongcare.excreta.model.data.remote

import android.util.Log
import com.project.meongcare.excreta.model.entities.ExcretaDetailGetResponse
import com.project.meongcare.excreta.model.entities.ExcretaPatchRequest
import com.project.meongcare.excreta.model.entities.ExcretaPostRequest
import com.project.meongcare.excreta.model.entities.ExcretaRecordGetRequest
import com.project.meongcare.excreta.model.entities.ExcretaRecordGetResponse
import com.project.meongcare.excreta.model.entities.ExcretaUploadRequest
import com.project.meongcare.excreta.utils.SUCCESS
import org.json.JSONObject
import javax.inject.Inject
Expand All @@ -16,14 +17,13 @@ class ExcretaRemoteDataSource

suspend fun postExcreta(
accessToken: String,
excretaPostRequest: ExcretaUploadRequest,
excretaPostRequest: ExcretaPostRequest,
): Int? {
try {
val postResponse =
excretaApiService.postExcreta(
accessToken,
excretaPostRequest.dto,
excretaPostRequest.file,
excretaPostRequest,
)

if (postResponse.code() != SUCCESS) {
Expand Down Expand Up @@ -120,14 +120,13 @@ class ExcretaRemoteDataSource

suspend fun patchExcreta(
accessToken: String,
excretaUploadRequest: ExcretaUploadRequest,
excretaPatchRequest: ExcretaPatchRequest,
): Int? {
try {
val patchResponse =
excretaApiService.patchExcreta(
accessToken,
excretaUploadRequest.dto,
excretaUploadRequest.file,
excretaPatchRequest,
)

if (patchResponse.code() != SUCCESS) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,27 +1,24 @@
package com.project.meongcare.excreta.model.data.remote

import com.project.meongcare.excreta.model.entities.ExcretaDetailGetResponse
import com.project.meongcare.excreta.model.entities.ExcretaPatchRequest
import com.project.meongcare.excreta.model.entities.ExcretaPostRequest
import com.project.meongcare.excreta.model.entities.ExcretaRecordGetResponse
import okhttp3.MultipartBody
import okhttp3.RequestBody
import retrofit2.Response
import retrofit2.http.Body
import retrofit2.http.DELETE
import retrofit2.http.GET
import retrofit2.http.Header
import retrofit2.http.Multipart
import retrofit2.http.PATCH
import retrofit2.http.POST
import retrofit2.http.Part
import retrofit2.http.Path
import retrofit2.http.Query

interface ExcretaService {
@Multipart
@POST("excreta")
suspend fun postExcreta(
@Header("AccessToken") accessToken: String,
@Part("dto") dto: RequestBody,
@Part file: MultipartBody.Part,
@Body excretaPostRequest: ExcretaPostRequest,
): Response<Int>

@GET("excreta/{dogId}")
Expand All @@ -43,11 +40,9 @@ interface ExcretaService {
@Query("excretaIds") excretaIds: IntArray,
): Response<Int>

@Multipart
@PATCH("excreta")
suspend fun patchExcreta(
@Header("AccessToken") accessToken: String,
@Part("dto") dto: RequestBody,
@Part file: MultipartBody.Part,
@Body excretaPatchRequest: ExcretaPatchRequest,
): Response<Int>
}
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
package com.project.meongcare.excreta.model.data.repository

import com.project.meongcare.excreta.model.entities.ExcretaDetailGetResponse
import com.project.meongcare.excreta.model.entities.ExcretaPatchRequest
import com.project.meongcare.excreta.model.entities.ExcretaPostRequest
import com.project.meongcare.excreta.model.entities.ExcretaRecordGetRequest
import com.project.meongcare.excreta.model.entities.ExcretaRecordGetResponse
import com.project.meongcare.excreta.model.entities.ExcretaUploadRequest

interface ExcretaRepository {
suspend fun postExcreta(
accessToken: String,
excretaUploadRequest: ExcretaUploadRequest,
excretaPostRequest: ExcretaPostRequest,
): Int?

suspend fun getExcretaRecord(
Expand All @@ -28,6 +29,6 @@ interface ExcretaRepository {

suspend fun patchExcreta(
accessToken: String,
excretaUploadRequest: ExcretaUploadRequest,
excretaPatchRequest: ExcretaPatchRequest,
): Int?
}
Loading

0 comments on commit c2d9e25

Please sign in to comment.