数码课堂
第二套高阶模板 · 更大气的阅读体验

Kotlin上传音频文件到服务器的实用方法

发布时间:2026-01-10 14:31:01 阅读:266 次

Kotlin实现音频文件上传

做音频类App开发时,经常需要把录音文件传到服务器。比如用户录了一段语音笔记,点个上传就能存到云端。这种功能其实不难,用Kotlin配合OkHttp就能搞定。

假设你已经录好了音频,路径是 /storage/emulated/0/Recordings/test.mp3,现在要把它发到后台接口 https://api.example.com/upload

添加网络权限和依赖

先在 AndroidManifest.xml 里加上网络权限:

<uses-permission android:name="android.permission.INTERNET" />

然后在 build.gradle 加上OkHttp依赖:

implementation 'com.squareup.okhttp3:okhttp:4.12.0'

编写上传代码

核心逻辑就是构建一个带文件的表单请求。下面是一个可以直接用的示例:

val file = File("/storage/emulated/0/Recordings/test.mp3")
val requestBody = MultipartBody.Builder().setType(MultipartBody.FORM)
    .addFormDataPart("file", file.name, RequestBody.create(MediaType.get("audio/mpeg"), file))
    .build()

val request = Request.Builder()
    .url("https://api.example.com/upload")
    .post(requestBody)
    .build()

OkHttpClient().newCall(request).enqueue(object : Callback {
    override fun onResponse(call: Call, response: Response) {
        if (response.isSuccessful) {
            println("上传成功")
        }
    }

    override fun onFailure(call: Call, e: IOException) {
        e.printStackTrace()
    }
})

这段代码会把本地音频作为表单字段发送。注意这里设置了正确的MIME类型 audio/mpeg,服务端能更准确地处理。

处理运行时权限

如果目标设备是Android 6.0以上,别忘了申请读取外部存储权限。可以在Activity里这样请求:

if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
    ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.READ_EXTERNAL_STORAGE), 1)
}

用户授权后才能访问录音文件。否则程序会因为读不到文件而报错。

显示上传进度

大文件上传时加个进度条体验更好。可以封装一个 ProgressRequestBody 来监听写入过程:

class ProgressRequestBody(private val requestBody: RequestBody, private val listener: (Int) -> Unit) : RequestBody() {
    override fun contentType() = requestBody.contentType()

    override fun contentLength() = requestBody.contentLength()

    override fun writeTo(sink: BufferedSink) {
        val countingSink = object : ForwardingSink(sink) {
            var bytesWritten = 0L

            override fun write(source: Buffer, byteCount: Long) {
                super.write(source, byteCount)
                bytesWritten += byteCount
                val progress = (bytesWritten * 100f / contentLength()).toInt()
                listener(progress)
            }
        }

        requestBody.writeTo(BufferedSink(countingSink))
    }
}

使用时包装原始请求体:

.addFormDataPart("file", file.name, ProgressRequestBody(RequestBody.create(MediaType.get("audio/mpeg"), file)) { progress ->
    runOnUiThread { /* 更新进度条 */ } 
})

这样就能实时看到上传进度了。