凌峰创科服务平台

Android如何上传文件到PHP服务器?

我们将使用 OkHttp 库来处理 Android 端的网络请求,因为它功能强大且易于使用,PHP 端将使用 $_FILES 全局变量来接收上传的文件。

Android如何上传文件到PHP服务器?-图1
(图片来源网络,侵删)

目录

  1. 准备工作
  2. 服务器端 (PHP)
    • 创建上传目录
    • 编写 upload.php 文件
    • 安全性考虑
  3. 客户端 (Android Studio)
    • 添加依赖
    • 添加网络权限
    • 编写文件选择器 UI
    • 编写上传逻辑
  4. 完整代码示例
  5. 常见问题与解决方案
    • $_FILES['file']['error'] 错误码
    • 上传失败,返回 null
    • 上传后文件名乱码
    • 上传大文件失败或超时

准备工作

  • Android Studio: 确保你已经安装了最新版本的 Android Studio。
  • PHP 环境: 你需要一台可以运行 PHP 的服务器(本地如 XAMPP/MAMP,或远程服务器)。
  • OkHttp 库: 我们将使用 OkHttp 3 或 4 版本。

服务器端 (PHP)

我们在服务器上创建一个用于接收文件的 PHP 脚本。

a. 创建上传目录

在你的网站根目录下(htdocswww),创建一个名为 uploads 的文件夹。确保这个文件夹有写入权限(在 Linux/Mac 上通常设置为 755,在 Windows 上确保 IIS 或 Apache 用户有写入权限)。

your_project_folder/
├── uploads/      <-- 文件将上传到这里
└── upload.php    <-- 接收文件的PHP脚本

b. 编写 upload.php 文件

your_project_folder 下创建 upload.php 文件,内容如下:

<?php
// 允许任何来源的请求(开发时使用,生产环境应限制为你的域名)
header("Access-Control-Allow-Origin: *");
// 允许的请求方法
header("Access-Control-Allow-Methods: POST, OPTIONS");
// 允许的请求头
header("Access-Control-Allow-Headers: Content-Type");
// 如果是预检请求(OPTIONS),直接返回成功
if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS') {
    http_response_code(200);
    exit();
}
// 检查请求方法是否为 POST
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
    // 检查文件是否存在
    if (isset($_FILES['file'])) {
        $file = $_FILES['file'];
        $file_name = $file['name'];
        $file_tmp_name = $file['tmp_name'];
        $file_size = $file['size'];
        $file_error = $file['error'];
        // --- 安全性检查 ---
        // 1. 检查上传是否成功
        if ($file_error !== UPLOAD_ERR_OK) {
            // 根据错误码返回不同的信息
            $error_message = "上传失败: ";
            switch ($file_error) {
                case UPLOAD_ERR_INI_SIZE:
                    $error_message .= "文件大小超过 php.ini 中的 upload_max_filesize 指令。";
                    break;
                case UPLOAD_ERR_FORM_SIZE:
                    $error_message .= "文件大小超过 HTML 表单中指定的 MAX_FILE_SIZE。";
                    break;
                case UPLOAD_ERR_PARTIAL:
                    $error_message .= "文件只有部分被上传。";
                    break;
                case UPLOAD_ERR_NO_FILE:
                    $error_message .= "没有文件被上传。";
                    break;
                default:
                    $error_message .= "发生未知错误。";
                    break;
            }
            echo json_encode(['success' => false, 'message' => $error_message]);
            exit;
        }
        // 2. 检查文件大小 ( 限制为 10MB)
        $max_size = 10 * 1024 * 1024; // 10MB
        if ($file_size > $max_size) {
            echo json_encode(['success' => false, 'message' => '文件太大,最大允许 10MB。']);
            exit;
        }
        // 3. 检查文件类型 (可选, 只允许图片)
        $allowed_types = ['image/jpeg', 'image/png', 'image/gif'];
        $file_type = mime_content_type($file_tmp_name); // 更准确获取MIME类型
        if (!in_array($file_type, $allowed_types)) {
            echo json_encode(['success' => false, 'message' => '不允许的文件类型。']);
            exit;
        }
        // --- 安全性检查结束 ---
        // 定义上传目录
        $upload_dir = 'uploads/';
        // 如果目录不存在,则创建
        if (!is_dir($upload_dir)) {
            mkdir($upload_dir, 0755, true);
        }
        // 生成唯一的文件名,避免文件名冲突
        $file_extension = pathinfo($file_name, PATHINFO_EXTENSION);
        $new_file_name = uniqid() . '.' . $file_extension;
        $destination = $upload_dir . $new_file_name;
        // 移动临时文件到最终目录
        if (move_uploaded_file($file_tmp_name, $destination)) {
            // 上传成功,返回成功信息和文件路径
            echo json_encode([
                'success' => true, 
                'message' => '文件上传成功!', 
                'file_path' => $destination,
                'file_name' => $new_file_name
            ]);
        } else {
            // 上传失败
            echo json_encode(['success' => false, 'message' => '文件移动失败。']);
        }
    } else {
        // 没有文件被上传
        echo json_encode(['success' => false, 'message' => '没有选择文件。']);
    }
} else {
    // 请求方法不是 POST
    echo json_encode(['success' => false, 'message' => '无效的请求方法。']);
}
?>

PHP 代码解释:

Android如何上传文件到PHP服务器?-图2
(图片来源网络,侵删)
  • header("Access-Control-Allow-Origin: *"): 允许任何来源的跨域请求。*在生产环境中,你应该将 `` 替换为你的 Android App 的域名**。
  • isset($_FILES['file']): 检查是否有名为 file 的文件被上传。这个 file 必须与 Android 端 MultipartBody.Part 的 name 对应
  • $_FILES['file']['error']: PHP 提供的文件上传错误码,用于诊断上传失败的原因。
  • move_uploaded_file(): 这是将上传的临时文件移动到最终存储位置的关键函数。
  • json_encode(): 将 PHP 数组转换为 JSON 字符串,方便 Android 解析。

客户端 (Android Studio)

a. 添加依赖

app/build.gradle 文件的 dependencies 代码块中添加 OkHttp 依赖:

dependencies {
    // ... 其他依赖
    implementation("com.squareup.okhttp3:okhttp:4.12.0") // 使用最新版本
}

然后点击 "Sync Now"。

b. 添加网络权限

app/src/main/AndroidManifest.xml 文件中添加网络权限和 INTERNET 权限:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">
    <!-- 必须的互联网权限 -->
    <uses-permission android:name="android.permission.INTERNET" />
    <application
        ...>
        ...
    </application>
</manifest>

c. 编写文件选择器 UI

app/src/main/res/layout/activity_main.xml 中添加一个按钮和一个用于显示状态的 TextView

Android如何上传文件到PHP服务器?-图3
(图片来源网络,侵删)
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:gravity="center"
    android:padding="16dp"
    tools:context=".MainActivity">
    <Button
        android:id="@+id/btn_select_file"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="选择文件" />
    <Button
        android:id="@+id/btn_upload_file"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="16dp"
        android:text="上传文件" />
    <TextView
        android:id="@+id
分享:
扫描分享到社交APP
上一篇
下一篇