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

使用THTTPClient无法向服务器发送文件的问题排查(Delphi 11)

Delphi THTTPClient 文件上传至PHP服务端失败问题排查与解决

问题背景

  • 环境:Embarcadero® Delphi 11.0 Version 28.0
  • 任务:将本地文件d:\1.txt上传至http://example.com/upload.php,保存至网站根目录
  • 问题:调用THTTPClient.Post后,服务器返回200状态码,但PHP服务端未接收到文件,$_FILES数组无有效数据

相关日志与代码

服务器日志

[19/Jan/2024:21:08:46 +0500] "POST /upload.php HTTP/1.0" 200 3507 "-" "Embarcadero URI Client/1.0"

原Delphi客户端代码

var
  HTTPClient: THTTPClient;
begin
  HTTPClient := THTTPClient.Create;
  try
    // 设置Content-Type请求头
    HTTPClient.CustomHeaders['Content-Type'] := 'application/octet-stream';
    // 上传文件至服务器
    HTTPClient.Post('http://example.com/upload.php', TFileStream.Create('d:\1.txt', fmOpenRead), nil);
  finally
    HTTPClient.Free;
  end;
end;

原PHP服务端代码

<?php
// 保存上传文件的路径
$targetPath = '/path/to/save/1.txt';
 
if ($_FILES['file']['error'] === UPLOAD_ERR_OK) {
    // 将上传文件移动到指定位置
    if (move_uploaded_file($_FILES['file']['tmp_name'], $targetPath)) {
        // 文件上传成功
        echo 'Success: File uploaded successfully.';
    } else {
        // 移动文件失败
        echo 'Error: Unable to move uploaded file.';
    }
} else {
    // 文件上传出错
    echo 'Error: File upload error.';
}?>

原因分析

  1. 请求格式不匹配:客户端设置的Content-Type: application/octet-stream是二进制流格式,但PHP的$_FILES仅支持解析**multipart/form-data**格式的表单文件上传请求,这种格式是HTTP文件上传的标准协议格式。
  2. 数据未按表单字段封装:客户端直接上传原始文件流,没有按照表单字段的结构封装数据,PHP无法识别该请求为文件上传请求,因此不会将数据写入$_FILES数组。

修复方案

1. 修改Delphi客户端代码

使用TMultipartFormData构建符合标准的表单上传请求,THTTPClient会自动处理正确的Content-Type和请求体结构:

var
  HTTPClient: THTTPClient;
  FormData: TMultipartFormData;
begin
  HTTPClient := THTTPClient.Create;
  FormData := TMultipartFormData.Create;
  try
    // 添加文件到表单,字段名'file'需与服务端$_FILES['file']对应
    // 第三个参数为文件MIME类型,文本文件可设为'text/plain'
    FormData.AddFile('file', 'd:\1.txt', 'text/plain');
    // 发送POST请求,无需手动设置Content-Type
    HTTPClient.Post('http://example.com/upload.php', FormData);
  finally
    // 务必释放资源
    FormData.Free;
    HTTPClient.Free;
  end;
end;

2. 优化PHP服务端代码

  • 修正目标路径为网站根目录的实际路径(例如/var/www/html/1.txt)
  • 添加权限检查与调试输出,便于排查问题:
<?php
// 调试:输出所有上传信息(上线前可删除)
var_dump($_FILES);
var_dump($_POST);

// 替换为网站根目录的实际路径
$targetPath = '/var/www/html/1.txt';
$targetDir = dirname($targetPath);

// 先检查目标目录是否存在且可写
if (!is_dir($targetDir)) {
    mkdir($targetDir, 0755, true);
}

if (isset($_FILES['file']) && $_FILES['file']['error'] === UPLOAD_ERR_OK) {
    if (is_writable($targetDir)) {
        if (move_uploaded_file($_FILES['file']['tmp_name'], $targetPath)) {
            echo 'Success: File uploaded successfully.';
        } else {
            echo 'Error: Failed to move file. Check file permissions.';
        }
    } else {
        echo 'Error: Target directory is not writable.';
    }
} else {
    $errorMsg = isset($_FILES['file']) ? 'Upload error code: ' . $_FILES['file']['error'] : 'No file received.';
    echo 'Error: ' . $errorMsg;
}
?>

关键说明

  • 表单字段名必须前后端一致:客户端AddFile的第一个参数'file',必须和服务端$_FILES['file']的索引完全匹配。
  • TMultipartFormData会自动生成正确的请求边界和Content-Type头,无需手动设置,避免格式错误。

内容的提问来源于stack exchange,提问作者ывапав

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 21:40:35