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

使用OkHttp(Kotlin)通过HTTP POST传文件时PHP端报错排查

问题描述

在Android设备上使用OkHttp库通过HTTP POST发送文件到远程服务器,客户端Kotlin代码、服务器PHP代码如下,调用正常但服务器报错PHP Notice: Undefined index: file。

客户端Kotlin代码

class MyUploader {
    suspend fun makeRequest(fileUrl : String, str : String): String {
        val okHttpClient = OkHttpClient()
        return withContext(Dispatchers.IO) {
            parseResponse(okHttpClient.newCall(createRequest(fileUrl,str)).execute())
        }
    }

    private fun createRequest(fileUrl: String,str: String): Request {
        val requestBody = str.toRequestBody()
        val formBody: RequestBody = MultipartBody.Builder()
            .addFormDataPart("file", "log.csv")
            .addFormDataPart("app", "Roaming QOS APP")
            .addPart(requestBody)
            .build()

        return Request.Builder()
            .post(formBody)
            .url(fileUrl)
            .build()
    }

    private fun parseResponse(response: Response): String {
        val body = response.body?.string() ?: ""
        return body
    }
}

调用参数:

fileUrl = "http://www.xxxxx.it/log.php"
str = 文件内容

服务器端PHP代码(log.php)

<?php

$file_path = "./";

$file_path = $file_path . basename( $_FILES['file']['name']);
if(move_uploaded_file($_FILES['file']['tmp_name'], $file_path) ){
    echo "success";
} else{
    echo "fail";
}
?>

服务器错误日志

[Wed Mar 06 17:37:33.536882 2024] [:error] [pid 453] [client 151.25.30.103:35244] PHP Notice: Undefined index: file in /home/web/qosapp/log.php on line 6

错误原因

客户端代码的MultipartBody构建存在两个问题:

  • addFormDataPart("file", "log.csv")只指定了表单字段名和文件名,但没有传入文件内容的RequestBody,服务器无法识别这个字段为文件上传字段。
  • 额外调用addPart(requestBody)把文件内容作为普通的请求体部分发送,这部分不会被PHP的$_FILES数组捕获,而是会在php://input里,和预期的文件上传逻辑不匹配。
修正方案

修改客户端的createRequest方法,将文件内容正确关联到file表单字段,同时移除多余的addPart调用:

private fun createRequest(fileUrl: String, str: String): Request {
    // 指定文件的MediaType,csv文件对应text/csv类型
    val mediaType = "text/csv; charset=utf-8".toMediaType()
    // 将文件内容转为带MediaType的RequestBody
    val fileRequestBody = str.toRequestBody(mediaType)
    
    val formBody: RequestBody = MultipartBody.Builder()
        .setType(MultipartBody.FORM) // 显式设置多表单类型(规范写法)
        .addFormDataPart(
            "file", // 表单字段名,对应服务器$_FILES['file']
            "log.csv", // 文件名
            fileRequestBody // 文件内容的RequestBody
        )
        .addFormDataPart("app", "Roaming QOS APP")
        .build()

    return Request.Builder()
        .post(formBody)
        .url(fileUrl)
        .build()
}

修改后,服务器端就能通过$_FILES['file']获取到上传的文件,正常执行后续的文件保存逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 08:30:56