首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

Android MultipartEntity 圖片上傳失敗排查:服務端權限與代碼細節檢查

     編輯:程式設計綜合問答

現象

使用 MultipartEntity 上傳圖片,無報錯但服務端未收到文件。PHP 端 move_uploaded_file 未生效。

排查步驟與解決方案

1. 檢查服務端臨時目錄權限 (最常見原因)


// Linux 服務器
ls -ld /tmp          # 檢查臨時目錄權限,需 www-data 可寫
ls -ld /var/www/uploads # 目標目錄權限,需 www-data 可寫

// PHP 腳本中檢查
$tmpFile = $_FILES['uploaded']['tmp_name'];
$destFile = '/var/www/uploads/' . $_FILES['uploaded']['name'];
if (is_uploaded_file($tmpFile)) {
    if (move_uploaded_file($tmpFile, $destFile)) {
        echo "success";
    } else {
        error_log("move_uploaded_file failed: " . error_get_last()['message']);
        // 通常是目標目錄無寫權限
    }
} else {
    error_log("No uploaded file in tmp: " . $tmpFile);
}

2. 客戶端代碼關鍵修正


// 關鍵:設置正確的 Content-Type,避免瀏覽器兼容模式導致邊界解析失敗
MultipartEntity entity = new MultipartEntity(HttpMultipartMode.STRICT); // 推薦 STRICT

// 文件部分:明確指定 MIME 類型
FileBody fileBody = new FileBody(new File(path), "image/png", "UTF-8"); // 或 ContentType.create("image/png")
entity.addPart("uploaded", fileBody); // 名稱需與 PHP $_FILES['uploaded'] 一致

// 可選:添加其他字段
entity.addPart("userId", new StringBody(userId, ContentType.TEXT_PLAIN));

// 設置請求實體
HttpPost post = new HttpPost(url);
post.setEntity(entity);

// 執行並檢查響應
HttpResponse response = client.execute(post);
int status = response.getStatusLine().getStatusCode();
String respBody = EntityUtils.toString(response.getEntity());
Log.d("Upload", "Status: " + status + ", Response: " + respBody);

3. PHP 端完整健壯代碼


 false, 'message' => ''];

if (!isset($_FILES['uploaded']) || $_FILES['uploaded']['error'] !== UPLOAD_ERR_OK) {
    $response['message'] = 'Upload error: ' . ($_FILES['uploaded']['error'] ?? 'No file');
    echo json_encode($response);
    exit;
}

$tmpName = $_FILES['uploaded']['tmp_name'];
$origName = basename($_FILES['uploaded']['name']);
// 安全:生成唯一文件名
$ext = strtolower(pathinfo($origName, PATHINFO_EXTENSION));
$allowedExt = ['jpg', 'jpeg', 'png', 'gif'];
if (!in_array($ext, $allowedExt)) {
    $response['message'] = 'Invalid file type';
    echo json_encode($response);
    exit;
}
$newName = uniqid('img_') . '.' . $ext;
$destPath = $targetDir . $newName;

if (move_uploaded_file($tmpName, $destPath)) {
    $response['success'] = true;
    $response['file'] = $newName;
    $response['path'] = $destPath;
} else {
    $response['message'] = 'Move failed: check directory permissions';
}

echo json_encode($response);
?>

現代替代方案:OkHttp / Retrofit (強烈推薦)


// OkHttp
RequestBody requestBody = new MultipartBody.Builder()
    .setType(MultipartBody.FORM)
    .addFormDataPart("uploaded", file.getName(),
        RequestBody.create(MediaType.parse("image/png"), file))
    .addFormDataPart("userId", userId)
    .build();

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

client.newCall(request).enqueue(new Callback() {
    @Override public void onResponse(Call call, Response response) {
        // 處理響應
    }
    @Override public void onFailure(Call call, IOException e) { }
});

總結檢查清單

  1. ✅ 服務端 upload_tmp_dir 與目標目錄權限 (www-data 可讀寫)
  2. ✅ PHP 檢查 $_FILES['uploaded']['error'] 為 UPLOAD_ERR_OK
  3. ✅ 客戶端 MultipartEntity(HttpMultipartMode.STRICT)
  4. ✅ FileBody 明確指定 MIME 類型
  5. ✅ 字段名 "uploaded" 前後端一致
  6. ✅ 查看服務端錯誤日誌 (error_log / Nginx/Apache error.log)
  7. 🚀 新專案直接用 OkHttp/Retrofit,避免 HttpClient 已棄用維護問題
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved