从 Android 应用程序将图像上传到后端但缺少 EXIF 数据

问题描述 投票:0回答:1

我正在开发一个 Android 应用程序,用户可以从设备的图库中选择多张照片并将其上传到后端服务器。为了实现这一目标,我使用

PickMultipleVisualMedia()
来获取所选图像的 URI,然后将它们传递给工作人员进行上传。

这是我实现照片选择器和工作人员的方法:

照片选择器实现:

private fun launchNewPhotoPicker(){
    newPicker.launch(PickVisualMediaRequest(ActivityResultContracts.PickVisualMedia.ImageOnly))
}

val newPicker = registerForActivityResult(ActivityResultContracts.PickMultipleVisualMedia(5)) { uris ->
    if (uris != null) {
        Log.d("PhotoPicker", "Selected URIs: ${uris}")
        runUploadImageWorker(uris)
    } else {
        Log.d("PhotoPicker", "No media selected")
    }
}

private fun runUploadImageWorker(uris: List<Uri>) {
    val strUris = uris.map { it.toString() }.toTypedArray()
    val data = Data.Builder()
        .putStringArray("uris", strUris)
        .build()

    val uploadImageRequest = OneTimeWorkRequestBuilder<UploadImageWorker>()
        .setInputData(data)
        .build()

    WorkManager.getInstance(requireContext()).enqueue(uploadImageRequest)
}

工人实施:

class UploadImageWorker(appContext: Context, workerParams: WorkerParameters) :
    Worker(appContext, workerParams) {

    override fun doWork(): Result {
        val uris = inputData.getStringArray("uris") ?: return Result.failure()

        val client = okhttp3.OkHttpClient()

        for (uriString in uris) {
            val uri = Uri.parse(uriString)
            val inputStream = applicationContext.contentResolver.openInputStream(uri)
            val requestBody = inputStream?.readBytes()?.toRequestBody("image/*".toMediaTypeOrNull())
            val body = requestBody?.let {
                MultipartBody.Part.createFormData("picture", UUID.randomUUID().toString(), it)
            } ?: return Result.failure()

            val multipartBody = MultipartBody.Builder()
                .setType(MultipartBody.FORM)
                .addPart(body)
                .build()

            val request = okhttp3.Request.Builder()
                .url("https://mywonderfullfakeurl.com/api/pictures")
                .post(multipartBody)
                .build()

            val response = client.newCall(request).execute()

            if (!response.isSuccessful) {
                val errorBody = response.body?.string() ?: "Unknown error"
                Log.d("error", errorBody)
                return Result.failure()
            }
        }

        return Result.success()
    }
}

但是,我注意到上传到后端服务器的图像缺少 EXIF 数据。使用 Kotlin 从 Android 应用上传图像时,如何确保保留 EXIF 数据?

android kotlin android-14
1个回答
0
投票

从图像文件中读取 EXIF 数据并将其添加到多部分请求中。

import android.media.ExifInterface
import okhttp3.*
import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.RequestBody.Companion.toRequestBody
import java.io.File
import java.util.*

val uris = inputData.getStringArray("uris") ?: return Result.failure()
val client = OkHttpClient()

for (uriString in uris) {
    val uri = Uri.parse(uriString)
    val inputStream = applicationContext.contentResolver.openInputStream(uri)
    val requestBody = inputStream?.readBytes()?.toRequestBody("image/*".toMediaTypeOrNull())
    val body = requestBody?.let {
        MultipartBody.Part.createFormData("picture", UUID.randomUUID().toString(), it)
    } ?: return Result.failure()

    val multipartBodyBuilder = MultipartBody.Builder()
        .setType(MultipartBody.FORM)
        .addPart(body)

    // This part is important 
    val exifInterface = ExifInterface(uri.path!!)
    val attributes = exifInterface.attributes
    for ((tag, value) in attributes) {
        multipartBodyBuilder.addFormDataPart("exif_$tag", value)
    }

    val multipartBody = multipartBodyBuilder.build()

    val request = Request.Builder()
        .url("https://mywonderfullfakeurl.com/api/pictures")
        .post(multipartBody)
        .build()

    val response = client.newCall(request).execute()

    if (!response.isSuccessful) {
        val errorBody = response.body?.string() ?: "Unknown error"
        Log.d("error", errorBody)
        return Result.failure()
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.