Android向PHP服务器上传音频后服务端文件大小为0如何解决
问题成因
- Android端Multipart协议格式缺失:你已经声明了
multipart/form-data请求类型并定义了边界标识,但上传文件时没有按照协议要求写入边界分隔头、字段描述信息,也没有在所有内容传输完成后写入结束边界标识,导致服务端接收到的请求体格式不规范,无法识别有效内容。 - PHP侧缺少必要的错误校验:你没有判断目标存储目录是否存在、是否有写入权限,也没有校验
fopen的返回值是否合法,若目录不存在或无写入权限,fwrite会直接执行失败,最终生成0字节空文件。 - 数据流处理逻辑不完整:Android端写入文件内容后仅执行了flush操作,未在请求提交前关闭输出流,可能存在数据未完全发送的情况。
解决办法
1. 安卓端代码修改
补全Multipart格式规范,修改addFilePart方法,在写入文件内容前添加字段头,全部内容写完后补充结束边界:
public void addFilePart(String fieldName, File uploadFile) throws IOException { String fileName = uploadFile.getName(); // 新增:写入multipart字段分隔头 outputStream.write(("--" + boundary + "\r\n").getBytes()); outputStream.write(("Content-Disposition: form-data; name=\"" + fieldName + "\"; filename=\"" + fileName + "\"\r\n").getBytes()); outputStream.write(("Content-Type: audio/amr\r\n\r\n").getBytes()); FileInputStream inputStream = new FileInputStream(uploadFile); byte[] buffer = new byte[4096]; int bytesRead = -1; while ((bytesRead = inputStream.read(buffer)) != -1) { outputStream.write(buffer, 0, bytesRead); Log.d("sending",buffer.toString()); } outputStream.write("\r\n".getBytes()); // 新增:文件内容结束换行 outputStream.flush(); inputStream.close(); } // 新增:在调用finish前执行该方法,写入结束边界 public void addEndBoundary() throws IOException { outputStream.write(("--" + boundary + "--\r\n").getBytes()); outputStream.flush(); outputStream.close(); // 关闭输出流 }
调用顺序调整为:创建MultipartUtility实例→调用addFilePart添加文件→调用addEndBoundary写入结束边界→调用finish获取响应。
2. PHP端代码修改
优先使用PHP内置的$_FILES处理multipart上传,同时增加目录权限校验:
$dir = $_SERVER['DOCUMENT_ROOT']."/uploads/feedbackmsg"; // 校验目录,不存在则自动创建 if (!is_dir($dir)) { mkdir($dir, 0755, true); } $filename = $dir.'/testing.amr'; // 用$_FILES接收上传文件,注意field名和安卓端传入的一致 if (isset($_FILES['audio']) && $_FILES['audio']['error'] == UPLOAD_ERR_OK) { move_uploaded_file($_FILES['audio']['tmp_name'], $filename); }
如果必须使用php://input读取原始流,需要额外解析multipart格式,过滤掉边界标识和字段头后再存储文件内容,否则保存的文件会包含多余的格式标识,导致音频无法正常播放。
内容的提问来源于stack exchange,提问作者Amit Yadav
相关产品推荐
相关产品推荐

