Kyle
10/10/2023, 7:24 PMsuspend fun createCert(...) {
//bunch of other logic here
val multipart = MultiPartFormDataContent(formData {
append("certification", cert, Headers.build {
append(HttpHeaders.ContentType, "application/json")
})
append("photo", certImage, Headers.build {
append(HttpHeaders.ContentType, "image/png")
append(HttpHeaders.ContentDisposition, "filename=$filename")
})
})
val newCert = apiClient.createCertification(multipart)
return newCert.id
but every time I call it I keep getting <http://io.ktor.utils.io|io.ktor.utils.io>.errors.EOFException: Premature end of stream: expected 3081 bytes
because of the photo. At the point I’m appending certImage it’s a ByteArray. I’m using ktorfit for the client
@POST("/certification")
suspend fun createCertification(
@Body map: MultiPartFormDataContent
): UserCertification
Any ideas why it would be failing consistently?Aleksei Tirman [JB]
10/11/2023, 5:01 AMtylerwilson
10/28/2023, 6:00 PMKyle
10/28/2023, 8:16 PMif let data = try? await certificationImageItem?.loadTransferable(type: Data.self) {
if let uiImage:UIImage = UIImage(data: data) {
let finalImage: Data = uiImage.jpegData(compressionQuality: 0.5)!
let imageByteArray = NSDataByteArrayKt.NSDatatoByteArray(data: finalImage)
}
I removed a bunch of my irrelivant code when pasting so I’m not 100% sure that that’ll compile correctly but it’s the important bits. and then in NSDataByteArrayKt,
@OptIn(ExperimentalForeignApi::class)
fun NSDatatoByteArray(data: NSData): ByteArray = ByteArray(data.length.toInt()).apply {
usePinned {
memcpy(it.addressOf(0), data.bytes, data.length)
}
}
@OptIn(ExperimentalForeignApi::class)
fun NSData.toByteArray(): ByteArray = ByteArray(this@toByteArray.length.toInt()).apply {
usePinned {
memcpy(it.addressOf(0), this@toByteArray.bytes, this@toByteArray.length)
}
}
but it didn’t work for me on the first try and I haven’t gone back to revisit it.tylerwilson
10/30/2023, 1:05 PMval data = formData {
append("\"p_comId\"", "${auth.companyId}")
append("\"p_customerId\"", "$customerId")
append("\"p_type\"", type)
append("\"p_image\"", buildPacket {
writeFully(image.asByteArray())
}, Headers.build {
append(HttpHeaders.ContentDisposition, "filename=\"${image.name()}\"")
append(HttpHeaders.ContentType, "image/jpeg")
})
}
and the 'ImageWrapper' for iOS:
constructor(image: UIImage, name: String) {
val compression: CGFloat = 0.7 as CGFloat
this.data = UIImageJPEGRepresentation(image, compression)
this.name = "$name.jpg"
}
actual fun name(): String {
return this.name ?: "Unknown"
}
actual fun size(): Int {
return data?.length?.toInt() ?: 0
}
@OptIn(ExperimentalForeignApi::class)
actual fun asByteArray(): ByteArray {
return ByteArray(size()).apply {
usePinned {pinned ->
data?.let {
memcpy(pinned.addressOf(0), it.bytes, it.length)
}
}
}
}
still no luck. trying to perhaps reduce the size of the image before sending, hoping that helps.