Android中Okhttp上传Uri包装的文件

Uri:通用资源标志符(Universal Resource Identifier, 简称"URI")。
Uri在安卓系统中应用很广泛,系统返回的文件一般都是Uri类型的无法直接读取,以往的办法是通过contentResolver读取到文件的真实路径,然后上传这个文件。麻烦不说,兼容性也没法保证。

通过阅读okhttp源码,模仿File的扩展方法给Uri也实现了一个扩展:

@SuppressLint("Recycle")
fun Uri.openInputStream(context:Context): InputStream? {
    val contentResolver = context.contentResolver
    return contentResolver.openInputStream(this)
        ?: contentResolver.openAssetFileDescriptor(this, "r")?.createInputStream()
}

fun Uri.asRequestBody(context:Context,contentType: MediaType? = null): RequestBody {
    return object : RequestBody() {
        override fun contentType(): MediaType? {
            return contentType
        }

        override fun writeTo(sink: BufferedSink) {
            openInputStream(context)?.run {
                source().use {
                    sink.writeAll(it)
                }
            }
        }
    }
}

使用示例,retrofit同理:

val uri = xxx
val httpClient = OkHttpClient()
val request = Request.Builder()
    .put(uri.asRequestBody(context))
    .url(xxx)
    .build()
httpClient.newCall(request).execute()

使用的时候需要注意几点:

  1. 拥有这个uri的读取权限,如果没有申请读写外部存储的权限就去读取sd卡文件那肯定不行。
  2. 确保uri本身是文件类型的,一般文件uri的scheme是file,例如file:///sdcard/download/123.mp3
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容