You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android设备通过Heroku上Spring Boot应用传MP4至AWS S3,Android端用何方法?

Android端上传MP4文件到Spring Boot服务的实现方法

你的Spring Boot后端通过POST /add接口接收multipart/form-data类型的请求,需要包含两个核心部分:

  • 名为file的文件参数(对应后端的@RequestParam("file") MultipartFile)
  • Product实体的各个表单字段参数(对应后端的@Valid Product)

下面是两种Android端常用的实现方式:

方法一:使用OkHttp实现

OkHttp是Android生态中最常用的网络库,适合灵活构建请求。

1. 添加依赖(Gradle)

implementation("com.squareup.okhttp3:okhttp:4.12.0")

2. 上传代码实现

import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.MultipartBody
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.RequestBody.Companion.asRequestBody
import java.io.File

fun uploadMp4(mp4File: File, productFields: Map<String, String>) {
    val client = OkHttpClient()

    // 构建MP4文件请求体
    val fileRequestBody = mp4File.asRequestBody("video/mp4".toMediaTypeOrNull())
    val filePart = MultipartBody.Part.createFormData("file", mp4File.name, fileRequestBody)

    // 构建表单请求体,添加文件和Product字段
    val requestBody = MultipartBody.Builder()
        .setType(MultipartBody.FORM)
        .addPart(filePart)
        .apply {
            // 遍历添加Product的所有字段,比如name、price等,需与后端Product类属性名一致
            productFields.forEach { (key, value) ->
                addFormDataPart(key, value)
            }
        }
        .build()

    val request = Request.Builder()
        .url("https://你的Heroku服务域名/add") // 替换为实际服务地址
        .post(requestBody)
        .build()

    // 异步发送请求,避免阻塞主线程
    client.newCall(request).enqueue(object : okhttp3.Callback {
        override fun onFailure(call: okhttp3.Call, e: IOException) {
            // 处理上传失败逻辑,比如提示用户
            e.printStackTrace()
        }

        override fun onResponse(call: okhttp3.Call, response: okhttp3.Response) {
            when {
                response.isSuccessful -> {
                    // 上传成功,可做后续处理
                }
                else -> {
                    // 处理后端返回的错误,比如读取错误信息
                    val errorMsg = response.body?.string()
                }
            }
            response.close()
        }
    })
}

注意事项

  • 替换代码中的服务URL为你Heroku部署的实际地址
  • productFields需包含Product实体的所有必填字段,键名要和后端Product类的属性名完全匹配
  • 在AndroidManifest.xml中添加网络权限:<uses-permission android:name="android.permission.INTERNET" />
  • Android 10+需注意文件访问权限,建议通过MediaStore获取MP4文件,避免直接操作外部存储

方法二:使用Retrofit实现

Retrofit是基于OkHttp的封装,代码更简洁,适合结构化的网络请求场景。

1. 添加依赖(Gradle)

implementation("com.squareup.retrofit2:retrofit:2.9.0")
implementation("com.squareup.retrofit2:converter-gson:2.9.0")
implementation("com.squareup.okhttp3:okhttp:4.12.0")

2. 定义Retrofit接口

import okhttp3.MultipartBody
import okhttp3.RequestBody
import retrofit2.Call
import retrofit2.http.Multipart
import retrofit2.http.POST
import retrofit2.http.Part
import retrofit2.http.PartMap

interface ProductUploadApi {
    @Multipart
    @POST("add")
    fun uploadProduct(
        @Part file: MultipartBody.Part,
        @PartMap productFields: Map<String, @JvmSuppressWildcards RequestBody>
    ): Call<Void>
}

3. 上传代码实现

import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
import okhttp3.RequestBody.Companion.toRequestBody
import okhttp3.MediaType.Companion.toMediaTypeOrNull

fun uploadWithRetrofit(mp4File: File, productFields: Map<String, String>) {
    val retrofit = Retrofit.Builder()
        .baseUrl("https://你的Heroku服务域名/") // 替换为服务根地址
        .addConverterFactory(GsonConverterFactory.create())
        .build()

    val api = retrofit.create(ProductUploadApi::class.java)

    // 构建文件Part
    val fileRequestBody = mp4File.asRequestBody("video/mp4".toMediaTypeOrNull())
    val filePart = MultipartBody.Part.createFormData("file", mp4File.name, fileRequestBody)

    // 转换Product字段为RequestBody Map
    val productBodyMap = mutableMapOf<String, RequestBody>()
    productFields.forEach { (key, value) ->
        productBodyMap[key] = value.toRequestBody("text/plain".toMediaTypeOrNull())
    }

    // 发送请求
    val call = api.uploadProduct(filePart, productBodyMap)
    call.enqueue(object : retrofit2.Callback<Void> {
        override fun onResponse(call: Call<Void>, response: retrofit2.Response<Void>) {
            if (response.isSuccessful) {
                // 上传成功处理
            } else {
                // 处理后端错误
            }
        }

        override fun onFailure(call: Call<Void>, t: Throwable) {
            // 请求失败处理
            t.printStackTrace()
        }
    })
}

注意事项

  • 若后端返回非空响应,可修改Call的泛型类型(比如Call<String>)来获取返回内容
  • 确保Product字段的键名与后端实体类属性完全一致,否则后端无法正确绑定参数
  • 同样需要申请网络权限和文件访问权限

内容的提问来源于stack exchange,提问作者Radek0582

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 17:17:06