使用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
相关产品推荐
相关产品推荐

