'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 |