'Error uploading Multipart to MongoDB using Ktor

I'm trying to upload a JPEG to MongoDB using Ktor and Kotlin but keep getting an error:

java.io.FileNotFoundException: /document/image:32: open failed: ENOENT (No such file or directory)

Please help if someone knows what I am doing wrong here

It is a strange error, because I'm sure that uri is ok. I can display an image in app with this.

First things first:

KTOR SIDE:

fun Route.uploadFile(
app: Application){


val client = KMongo.createClient()
val database = client.getDatabase(IMAGES_DATABASE_NAME)
val bucket = GridFSBuckets.create(database, "images")

post("/upload_photo") {
    try {
        val multipartData = call.receiveMultipart()

        multipartData.forEachPart { part ->
            if (part is PartData.FileItem) {
                val fileName = part.originalFileName as String
                withContext(Dispatchers.IO) {
                    bucket.uploadFromStream(fileName, part.streamProvider())
                }
                call.respond(
                    message = ApiResponse(
                        success = true,
                        message = ""
                    )
                )
            } else {
                call.respond(
                    message = ApiResponse(
                        success = false,
                        message = ""
                    )
                )
            }
        }
    } catch (e: Exception) {
        app.log.info("Error: ${e.message}")
        call.respond(
            message = ApiResponse(
                message = "Error: ${e.message}",
                success = false
            ),
            status = HttpStatusCode.BadRequest
        )
    }
}

API INTERFACE:

@Multipart
    @POST("/upload_photo")
    suspend fun uploadPhoto(
        @Part filePart: MultipartBody.Part
    ):ApiResponse

Now, I suppose that the problem occures on kotlin Android App side:

Function where the problem occures:

override suspend fun uploadFile(photo: Uri): ApiResponse {
    return try {
        val file = photo.path?.let { File(it) }
        val requestBody = file!!.asRequestBody()
        val body = MultipartBody.Part.createFormData("photo",file.name, requestBody )
        Log.d("Upload", body.toString())
        ktorApi.uploadPhoto(body)
    } catch (e: Exception) {
        Log.d("Upload: ", "{ $e.message }")
        ApiResponse(
            success = false,
            error = e
        )
    }
}


Solution 1:[1]

I found a solution to my problem. To make a post with Uri possible is it necessary to create a temporary file in local cashe. For example with the method like thise:

private fun createFileFromUri(name: String, uri: Uri, context: Context): File? {
return try {
    val stream = context.contentResolver.openInputStream(uri)
    val file =
        File.createTempFile(
            "${name}_${System.currentTimeMillis()}",
            ".jpg",
            context.cacheDir
        )
    FileUtils.copyInputStreamToFile(stream, file)  // Use this one import org.apache.commons.io.FileUtils
    file
} catch (e: Exception) {
    e.printStackTrace()
    null
}

}

and a dependency in gradle :

implementation group: 'commons-io', name: 'commons-io', version: '2.7'
implementation group: 'org.apache.commons', name: 'commons-text', version: '1.9'

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Adrian Czerwi?ski