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

Android应用自动上传内部存储文本文件至PHP服务器问题排查

问题解决:Android内部存储文件上传至PHP服务器

核心问题分析

你的代码存在两个关键问题导致上传失败:

  1. 文件路径错误:你使用了外部存储路径Environment.getExternalStorageDirectory(),但目标文件位于App私有内部存储,路径不匹配;
  2. 上传格式不兼容:PHP代码通过$_FILES["fileToUpload"]接收表单式文件,而你的Android代码直接传递文件流,PHP无法识别该字段。

步骤1:正确获取内部存储文件路径

App私有内部存储的根目录为/data/data/[你的包名]/files/,无需申请权限即可访问,获取文件的代码如下:

在Activity中获取:

// 获取内部存储根目录下的textFile.txt
File file = new File(getFilesDir(), "textFile.txt");

在Service/BroadcastReceiver中获取(需传入Context):

// 假设已有Context实例context
File file = new File(context.getFilesDir(), "textFile.txt");

验证文件存在性:上传前先检查文件是否存在,避免空指针或找不到文件的问题:

if (!file.exists()) {
    Log.e("Upload", "目标文件不存在:" + file.getAbsolutePath());
    return;
}

步骤2:修改Android上传代码(适配PHP接收格式)

PHP需要接收multipart/form-data格式的表单数据,因此你需要改用Multipart方式上传。以下提供两种实现方案:

方案1:使用OkHttp(推荐,适配高版本Android)

OkHttp是Android官方推荐的网络库,替代已被弃用的DefaultHttpClient。

  1. 在build.gradle(Module level)添加依赖:
implementation 'com.squareup.okhttp3:okhttp:4.12.0'
  1. 异步上传代码(避免主线程阻塞):
String url = "https://path-to/file-upload3.php";
File file = new File(getFilesDir(), "textFile.txt");

if (!file.exists()) {
    Log.e("UploadError", "文件不存在:" + file.getAbsolutePath());
    return;
}

OkHttpClient client = new OkHttpClient();

// 构建Multipart表单,字段名必须和PHP的"fileToUpload"一致
RequestBody requestBody = new MultipartBody.Builder()
        .setType(MultipartBody.FORM)
        .addFormDataPart(
                "fileToUpload", 
                file.getName(), 
                RequestBody.create(file, MediaType.parse("text/plain"))
        )
        .build();

Request request = new Request.Builder()
        .url(url)
        .post(requestBody)
        .build();

// 异步执行请求
client.newCall(request).enqueue(new Callback() {
    @Override
    public void onFailure(Call call, IOException e) {
        e.printStackTrace();
        Log.e("UploadFail", "上传失败:" + e.getMessage());
    }

    @Override
    public void onResponse(Call call, Response response) throws IOException {
        if (response.isSuccessful()) {
            String responseMsg = response.body().string();
            Log.d("UploadSuccess", "服务器响应:" + responseMsg);
        } else {
            Log.e("UploadError", "服务器返回错误码:" + response.code());
        }
    }
});

方案2:使用Apache HttpClient(兼容旧版本)

如果必须使用DefaultHttpClient,需要引入依赖并修改上传逻辑:

  1. 添加依赖:
implementation 'org.apache.httpcomponents:httpmime:4.5.14'
implementation 'org.apache.httpcomponents:httpclient-android:4.5.14'
  1. 上传代码(需放在子线程执行):
String url = "https://path-to/file-upload3.php";
File file = new File(getFilesDir(), "textFile.txt");

if (!file.exists()) {
    Log.e("UploadError", "文件不存在:" + file.getAbsolutePath());
    return;
}

new Thread(new Runnable() {
    @Override
    public void run() {
        try {
            HttpClient httpclient = new DefaultHttpClient();
            HttpPost httppost = new HttpPost(url);

            // 构建Multipart实体,字段名匹配PHP的fileToUpload
            MultipartEntityBuilder builder = MultipartEntityBuilder.create();
            builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
            builder.addBinaryBody(
                    "fileToUpload", 
                    file, 
                    ContentType.DEFAULT_BINARY, 
                    file.getName()
            );

            httppost.setEntity(builder.build());
            HttpResponse response = httpclient.execute(httppost);

            // 读取服务器响应
            String responseMsg = EntityUtils.toString(response.getEntity(), "UTF-8");
            Log.d("UploadResponse", responseMsg);

        } catch (Exception e) {
            e.printStackTrace();
            Log.e("UploadException", e.getMessage());
        }
    }
}).start();

步骤3:修复PHP代码逻辑问题

你的PHP代码存在校验顺序错误(先上传后校验),且未确保uploads目录存在,修改后的代码如下:

<?php
$target_dir = "uploads/";
// 确保uploads目录存在,不存在则创建
if (!file_exists($target_dir)) {
    mkdir($target_dir, 0777, true);
}
$target_file = $target_dir . basename($_FILES["fileToUpload"]["name"]);
$uploadOk = 1;
$imageFileType = strtolower(pathinfo($target_file, PATHINFO_EXTENSION));

// 检查文件是否已存在
if (file_exists($target_file)) {
    echo "Sorry, file already exists.";
    $uploadOk = 0;
}

// 检查文件大小(限制500KB)
if ($_FILES["fileToUpload"]["size"] > 500000) {
    echo "Sorry, your file is too large.";
    $uploadOk = 0;
}

// 允许的文件格式
$allowedTypes = array("jpg", "png", "jpeg", "gif", "txt");
if (!in_array($imageFileType, $allowedTypes)) {
    echo "Sorry, only JPG, JPEG, PNG, GIF and TXT files are allowed.";
    $uploadOk = 0;
}

// 执行上传或返回错误
if ($uploadOk == 0) {
    echo "Sorry, your file was not uploaded.";
} else {
    if (move_uploaded_file($_FILES["fileToUpload"]["tmp_name"], $target_file)) {
        echo "The file " . basename($_FILES["fileToUpload"]["name"]) . " has been uploaded.";
    } else {
        echo "Sorry, there was an error uploading your file.";
    }
}
?>

额外注意事项

  • 网络请求线程:Android禁止在主线程执行网络请求,必须将上传代码放在子线程(如OkHttp的异步回调、Thread、AsyncTask);
  • 权限:内部存储无需任何权限,若后续切换到外部存储,需在AndroidManifest.xml添加权限并在高版本Android中申请动态权限;
  • 调试:通过Logcat查看服务器响应信息,排查上传失败的具体原因(如文件不存在、服务器返回错误等)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 00:37:16