mirror of
https://github.com/pawelorzech/Swoosh.git
synced 2026-03-31 20:15:41 +00:00
feat: add media upload API endpoints and repository method for video/audio
- Create MediaModels.kt with MediaUploadResponse and UploadedMedia data classes - Add uploadMedia() and uploadMediaThumbnail() to GhostApiService - Add uploadMediaFile(uri) to PostRepository with MIME detection
This commit is contained in:
parent
807c6d559e
commit
2410d05bd6
3 changed files with 60 additions and 3 deletions
|
|
@ -1,6 +1,7 @@
|
||||||
package com.swoosh.microblog.data.api
|
package com.swoosh.microblog.data.api
|
||||||
|
|
||||||
import com.swoosh.microblog.data.model.GhostSite
|
import com.swoosh.microblog.data.model.GhostSite
|
||||||
|
import com.swoosh.microblog.data.model.MediaUploadResponse
|
||||||
import com.swoosh.microblog.data.model.MembersResponse
|
import com.swoosh.microblog.data.model.MembersResponse
|
||||||
import com.swoosh.microblog.data.model.PageWrapper
|
import com.swoosh.microblog.data.model.PageWrapper
|
||||||
import com.swoosh.microblog.data.model.PagesResponse
|
import com.swoosh.microblog.data.model.PagesResponse
|
||||||
|
|
@ -114,6 +115,20 @@ interface GhostApiService {
|
||||||
@Part file: MultipartBody.Part,
|
@Part file: MultipartBody.Part,
|
||||||
@Part("purpose") purpose: RequestBody
|
@Part("purpose") purpose: RequestBody
|
||||||
): Response<ImageUploadResponse>
|
): Response<ImageUploadResponse>
|
||||||
|
|
||||||
|
@Multipart
|
||||||
|
@POST("ghost/api/admin/media/upload/")
|
||||||
|
suspend fun uploadMedia(
|
||||||
|
@Part file: MultipartBody.Part,
|
||||||
|
@Part("ref") ref: RequestBody? = null
|
||||||
|
): Response<MediaUploadResponse>
|
||||||
|
|
||||||
|
@Multipart
|
||||||
|
@POST("ghost/api/admin/media/thumbnail/upload/")
|
||||||
|
suspend fun uploadMediaThumbnail(
|
||||||
|
@Part file: MultipartBody.Part,
|
||||||
|
@Part("ref") ref: RequestBody? = null
|
||||||
|
): Response<MediaUploadResponse>
|
||||||
}
|
}
|
||||||
|
|
||||||
data class ImageUploadResponse(
|
data class ImageUploadResponse(
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
package com.swoosh.microblog.data.model
|
||||||
|
|
||||||
|
data class MediaUploadResponse(
|
||||||
|
val media: List<UploadedMedia>
|
||||||
|
)
|
||||||
|
|
||||||
|
data class UploadedMedia(
|
||||||
|
val url: String,
|
||||||
|
val ref: String?,
|
||||||
|
val fileName: String?
|
||||||
|
)
|
||||||
|
|
@ -113,8 +113,8 @@ class PostRepository(private val context: Context) {
|
||||||
suspend fun uploadImage(uri: Uri): Result<String> =
|
suspend fun uploadImage(uri: Uri): Result<String> =
|
||||||
withContext(Dispatchers.IO) {
|
withContext(Dispatchers.IO) {
|
||||||
try {
|
try {
|
||||||
val file = copyUriToTempFile(uri)
|
|
||||||
val mimeType = context.contentResolver.getType(uri) ?: "image/jpeg"
|
val mimeType = context.contentResolver.getType(uri) ?: "image/jpeg"
|
||||||
|
val file = copyUriToTempFile(uri, ".jpg")
|
||||||
val requestBody = file.asRequestBody(mimeType.toMediaType())
|
val requestBody = file.asRequestBody(mimeType.toMediaType())
|
||||||
val part = MultipartBody.Part.createFormData("file", file.name, requestBody)
|
val part = MultipartBody.Part.createFormData("file", file.name, requestBody)
|
||||||
val purpose = "image".toRequestBody("text/plain".toMediaType())
|
val purpose = "image".toRequestBody("text/plain".toMediaType())
|
||||||
|
|
@ -156,10 +156,41 @@ class PostRepository(private val context: Context) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun copyUriToTempFile(uri: Uri): File {
|
/**
|
||||||
|
* Uploads a media file (video or audio) to the Ghost media upload endpoint.
|
||||||
|
* Determines MIME type from the content resolver. Returns the uploaded URL on success.
|
||||||
|
*/
|
||||||
|
suspend fun uploadMediaFile(uri: Uri): Result<String> =
|
||||||
|
withContext(Dispatchers.IO) {
|
||||||
|
try {
|
||||||
|
val mimeType = context.contentResolver.getType(uri) ?: "application/octet-stream"
|
||||||
|
val extension = when {
|
||||||
|
mimeType.startsWith("video/") -> mimeType.substringAfter("video/").let { ".$it" }
|
||||||
|
mimeType.startsWith("audio/") -> mimeType.substringAfter("audio/").let { ".$it" }
|
||||||
|
else -> ""
|
||||||
|
}
|
||||||
|
val file = copyUriToTempFile(uri, extension)
|
||||||
|
val requestBody = file.asRequestBody(mimeType.toMediaType())
|
||||||
|
val part = MultipartBody.Part.createFormData("file", file.name, requestBody)
|
||||||
|
|
||||||
|
val response = getApi().uploadMedia(part)
|
||||||
|
file.delete()
|
||||||
|
|
||||||
|
if (response.isSuccessful) {
|
||||||
|
val url = response.body()!!.media.first().url
|
||||||
|
Result.success(url)
|
||||||
|
} else {
|
||||||
|
Result.failure(Exception("Media upload failed ${response.code()}"))
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Result.failure(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun copyUriToTempFile(uri: Uri, extension: String = ".jpg"): File {
|
||||||
val inputStream = context.contentResolver.openInputStream(uri)
|
val inputStream = context.contentResolver.openInputStream(uri)
|
||||||
?: throw IllegalStateException("Cannot open URI")
|
?: throw IllegalStateException("Cannot open URI")
|
||||||
val tempFile = File.createTempFile("upload_", ".jpg", context.cacheDir)
|
val tempFile = File.createTempFile("upload_", extension, context.cacheDir)
|
||||||
FileOutputStream(tempFile).use { output ->
|
FileOutputStream(tempFile).use { output ->
|
||||||
inputStream.copyTo(output)
|
inputStream.copyTo(output)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue