원석
09/07/2023, 9:37 AM"<http://io.ktor.utils.io|io.ktor.utils.io>.charsets.MalformedInputException: Failed to convert Bytes to String using UTF-8".
This problem arises during the process of loading images in a Kotlin Multiplatform project, specifically on iOS Darwin. Has anyone encountered a similar issue or successfully resolved it? I could really use some help.Sam
09/07/2023, 9:39 AM원석
09/07/2023, 9:48 AM<https://sample-url.com/20200419_34/1587264166705H6VSV_JPEG/sampleimage.jpeg.jpg>
During the image loading process, I am utilizing the Kamel library, which is known for facilitating image loading in Kotlin Multiplatform projects. You can find more about it here: Kamel Library on GitHub.
Additionally, here is a snippet of my configuration code:
defaultRequest {
url {
protocol = URLProtocol.HTTPS
host = "SAMPLE_SERVER_HOST"
port = if (isDebug) 8443 else DEFAULT_PORT
}
header(
HttpHeaders.ContentType,
ContentType.Application.Json
)
}
install(ContentNegotiation) {
json(
Json {
prettyPrint = true
isLenient = true
encodeDefaults = true
}
)
}
ContentEncoding {
gzip()
deflate()
}
Charsets {
register(UTF_8)
}
install(Auth) {
bearer {
loadTokens {
BearerTokens(
accessToken = localPreferenceLocalDataSource.getAccessToken(),
refreshToken = String.Companion.Empty
)
}
}
}
install(Logging) {
level = LogLevel.ALL
logger = object : Logger {
override fun log(message: String) {
Napier.i(message)
}
}
}
install(HttpTimeout) {
requestTimeoutMillis = 50_000
}
Sam
09/07/2023, 9:51 AMCharsets
configuration block I think you are instructing the HTTP client to try and treat everything it receives as text data. Does it work better if you just remove that block?Sam
09/07/2023, 9:51 AMSam
09/07/2023, 9:54 AM원석
09/07/2023, 9:59 AM// String
asyncPainterResource(data = "<https://www.example.com/image.jpg>")
// Ktor Url
asyncPainterResource(data = Url("<https://www.example.com/image.jpg>"))
// URI
asyncPainterResource(data = URI("<https://www.example.com/image.png>"))
// File (JVM, Native)
asyncPainterResource(data = File("/path/to/image.png"))
// File (JS)
asyncPainterResource(data = File(org.w3c.files.File(arrayOf(blob), "/path/to/image.png")))
// URL
asyncPainterResource(data = URL("<https://www.example.com/image.jpg>"))
Sam
09/07/2023, 10:01 AM원석
09/07/2023, 10:06 AMasyncPainterResource
method. Here is the snippet from my code where the image is loaded:
restaurant.images.firstOrNull()?.let { imageUrl ->
KamelImage(
resource = asyncPainterResource(
data = imageUrl
),
contentDescription = null,
modifier = Modifier
.background(
brush = shimmerBrush(
targetValue = 1300f,
showShimmer = showShimmer.value
)
),
onLoading = { progress ->
if (progress == 1.0f) {
showShimmer.value = false
}
},
onFailure = {
showShimmer.value = false
},
contentScale = ContentScale.Crop
)
} ?: Image(
painter = painterResource(SharedRes.images.img_restaurant_placeholder),
contentDescription = null)
In this snippet, asyncPainterResource
is passed a URL as a string (retrieved as imageUrl
from the first image in the restaurant’s image list) and it’s used to load the image with the Kamel library. The code also includes handling for loading progress and failure, utilizing a shimmer effect during the loading process.
I hope this helps to clarify! Let me know if there’s any other information you need😀Sam
09/07/2023, 10:11 AM원석
09/07/2023, 10:27 AMUncaught Kotlin exception: io.ktor.utils.io.charsets.MalformedInputException: Failed to convert Bytes to String using UTF-8
kfun:kotlin.Throwable#<init>(kotlin.String?){} + 123
kfun:io.ktor.utils.io.charsets.MalformedInputException#<init>(kotlin.String){} + 119
kfun:io.ktor.utils.io.charsets#decode__at__io.ktor.utils.io.charsets.CharsetDecoder(io.ktor.utils.io.core.Input;kotlin.text.Appendable;kotlin.Int){}<http://kotlin.Int|kotlin.Int> + 1507
kfun:io.ktor.utils.io.charsets#decode__at__io.ktor.utils.io.charsets.CharsetDecoder(io.ktor.utils.io.core.Input;kotlin.Int){}kotlin.String + 403
kfun:io.ktor.utils.io.core#String(kotlin.ByteArray;kotlin.Int;kotlin.Int;io.ktor.utils.io.charsets.Charset){}kotlin.String + 979
kfun:io.ktor.http.decodeImpl#internal + 3663
kfun:io.ktor.http.decodeScan#internal + 475
kfun:io.ktor.http#decodeURLPart__at__kotlin.String(<http://kotlin.Int;kotlin.Int;io.ktor.utils.io.charsets.Charset|kotlin.Int;kotlin.Int;io.ktor.utils.io.charsets.Charset>){}kotlin.String + 215
kfun:io.ktor.http#decodeURLPart$default__at__kotlin.String(<http://kotlin.Int;kotlin.Int;io.ktor.utils.io.charsets.Charset?;kotlin.Int|kotlin.Int;kotlin.Int;io.ktor.utils.io.charsets.Charset?;kotlin.Int>){}kotlin.String + 491
kfun:io.ktor.http.URLBuilder#<get-pathSegments>(){}kotlin.collections.List<kotlin.String> + 687
kfun:io.ktor.http.URLBuilder#build(){}io.ktor.http.Url + 375
kfun:io.ktor.http#Url(kotlin.String){}io.ktor.http.Url + 171
kfun:io.kamel.core.mapper.object-1.map#internal + 111
kfun:io.kamel.core.utils#mapInput__at__io.kamel.core.config.KamelConfig(kotlin.Any;kotlin.reflect.KClass<*>){}kotlin.Any + 547
kfun:io.kamel.core#loadCachedResourceOrNull__at__io.kamel.core.config.KamelConfig(kotlin.Any;io.kamel.core.cache.Cache<kotlin.Any,0:0>;kotlin.reflect.KClass<*>){0§<kotlin.Any>}io.kamel.core.Resource<0:0>? + 295
kfun:io.kamel.core#loadCachedResourceOrNull$default__at__io.kamel.core.config.KamelConfig(kotlin.Any;io.kamel.core.cache.Cache<kotlin.Any,0:0>;kotlin.reflect.KClass<*>?;kotlin.Int){0§<kotlin.Any>}io.kamel.core.Resource<0:0>? + 375
Sam
09/07/2023, 10:33 AMSam
09/07/2023, 10:34 AMSam
09/07/2023, 10:35 AMSam
09/07/2023, 10:40 AM%
symbols in general원석
09/07/2023, 10:40 AMSam
09/07/2023, 10:41 AM원석
09/07/2023, 10:43 AM원석
09/07/2023, 11:16 AMrestaurant.images.firstOrNull()?.let { imageUrl ->
val decodedUrl = imageUrl.decodeURLPart(charset = Charsets.ISO_8859_1)
KamelImage(
resource = asyncPainterResource(
data = Url(decodedUrl)
),
contentDescription = null,
modifier = Modifier
.background(
brush = shimmerBrush(
targetValue = 1300f,
showShimmer = showShimmer.value
)
),
onLoading = { progress ->
if (progress == 1.0f) {
showShimmer.value = false
}
},
onFailure = {
showShimmer.value = false
},
contentScale = ContentScale.Crop
)
} ?: Image(
painter = painterResource(SharedRes.images.img_restaurant_placeholder),
contentDescription = null)
I am really grateful for your assistance and cooperation throughout this process. Thank you once again 👍Sam
09/07/2023, 11:58 AM