使用Coil在Compose中加载含波斯语文件名图片时遇显示异常
解决Coil加载含波斯语/波斯数字文件名图片失败问题
问题现象
使用Coil的rememberAsyncImagePainter加载图片时,若响应头的Content-Disposition包含波斯语及波斯数字文件名(如تست۳_128.jpg),会抛出IllegalArgumentException异常,提示Unexpected char 0x62a in content-disposition value。
解决方案
问题根源是OkHttp默认解析Content-Disposition时仅支持ASCII字符,不兼容非ASCII文件名。通过自定义OkHttp拦截器修正响应头即可解决:
1. 编写自定义拦截器
可选两种处理方式:
方式一:移除filename参数(简单直接)
如果不需要保留文件名信息,直接移除Content-Disposition中的filename部分:
class FixContentDispositionInterceptor : Interceptor { override fun intercept(chain: Interceptor.Chain): Response { val response = chain.proceed(chain.request()) val contentDisposition = response.header("Content-Disposition") ?: return response // 只保留attachment; 部分,移除filename参数 val fixedDisposition = contentDisposition.substringBefore("filename=").trimEnd(';') return response.newBuilder() .header("Content-Disposition", fixedDisposition) .build() } }
方式二:编码非ASCII文件名(保留文件名)
按照RFC 5987标准对非ASCII文件名进行UTF-8编码,让OkHttp能正确解析:
import java.net.URLEncoder class FixContentDispositionInterceptor : Interceptor { override fun intercept(chain: Interceptor.Chain): Response { val response = chain.proceed(chain.request()) val contentDisposition = response.header("Content-Disposition") ?: return response val filenameRegex = Regex("filename=\"([^\"]+)\"") val matchResult = filenameRegex.find(contentDisposition) ?: return response val originalFilename = matchResult.groupValues[1] // 编码为RFC 5987兼容格式 val encodedFilename = "filename*=UTF-8''${URLEncoder.encode(originalFilename, "UTF-8")}" val fixedDisposition = contentDisposition.replace(filenameRegex, encodedFilename) return response.newBuilder() .header("Content-Disposition", fixedDisposition) .build() } }
2. 配置Coil使用自定义OkHttp客户端
将拦截器添加到OkHttp客户端,并配置给Coil的ImageLoader:
val okHttpClient = OkHttpClient.Builder() .addInterceptor(FixContentDispositionInterceptor()) .build() val imageLoader = ImageLoader.Builder(context) .okHttpClient(okHttpClient) .build()
3. 在Compose中使用自定义ImageLoader
修改rememberAsyncImagePainter的参数,传入自定义的ImageLoader:
val a = rememberAsyncImagePainter( model = selfUser.imageUrl, contentScale = ContentScale.Crop, imageLoader = imageLoader, onSuccess = { Log.d("mohaTest", "HeaderAvatar:onSuccess") }, onError = { Log.d("mohaTest", "HeaderAvatar: ${it.result.throwable}") } )
原理说明
Coil底层依赖OkHttp处理网络请求,而OkHttp默认遵循RFC 2616规范,仅支持ASCII字符的文件名。通过拦截器修改响应头,要么移除导致解析失败的filename参数,要么将其编码为RFC 5987兼容的UTF-8格式,就能避免解析异常,正常加载图片。
内容的提问来源于stack exchange,提问作者Moha.AZ
相关产品推荐
相关产品推荐

