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

MT4(C语言环境)基于WinInet.dll上传图片至PHP服务器失败问题求助

问题分析与修复方案

让我来帮你排查下问题,你的代码里有几个关键细节出错,导致服务器收不到上传的图片,咱们一步步来修正:

核心问题1:没有读取真实的图片二进制内容

你在frmdata里写的file contents here是占位符,但实际并没有把图片的真实数据读取进来——服务器自然收不到有效文件。在MT4里必须先读取图片的二进制内容,再拼到请求里。

核心问题2:边界字符串格式错误

你的请求头里的边界是---------------------------7d82751e2bc0858,但表单数据里的开头多了一个横杠,结尾也没按multipart规范加--。正确的multipart格式要求:

  • 每个字段的开头是--[边界]
  • 整个请求的结尾是--[边界]--

核心问题3:宽字符函数与二进制数据不兼容

你用了InternetOpenW这类宽字符版本的WinInet函数,但图片是二进制数据,宽字符编码会破坏二进制内容,应该改用ANSI版本的函数(比如InternetOpenA)。

核心问题4:文件路径转义错误

C:\\Users\descarga.png里的\d没有转义,应该写成C:\\Users\\descarga.png,否则MT4无法正确识别文件路径。


修复后的MT4代码示例

bool UploadImageToServer()
{
    string filePath = "C:\\Users\\descarga.png";
    string boundary = "---------------------------7d82751e2bc0858";
    
    // 检查文件是否存在
    if(!FileIsExist(filePath))
    {
        Print("文件不存在:", filePath);
        return false;
    }
    
    // 设置文件类型(可根据扩展名动态判断,这里简化为png)
    string fileType = "image/png";
    
    // 读取图片二进制内容
    int fileHandle = FileOpen(filePath, FILE_READ | FILE_BIN);
    if(fileHandle == INVALID_HANDLE)
    {
        Print("打开文件失败,错误码:", GetLastError());
        return false;
    }
    int fileSize = FileSize(fileHandle);
    uchar fileData[];
    ArrayResize(fileData, fileSize);
    FileReadArray(fileHandle, fileData, 0, fileSize);
    FileClose(fileHandle);
    
    // 构造multipart表单的前后缀
    string preData = "--" + boundary + "\r\n"
                   + "Content-Disposition: form-data; name=\"uploadedfile\"; filename=\"" + StringGetFile(filePath) + "\"\r\n"
                   + "Content-Type: " + fileType + "\r\n\r\n";
    
    string postData = "\r\n--" + boundary + "--\r\n";
    
    // 合并所有发送数据:前缀 + 二进制图片 + 后缀
    int totalSize = StringLen(preData) + fileSize + StringLen(postData);
    uchar sendBuffer[];
    ArrayResize(sendBuffer, totalSize);
    
    StringToCharArray(preData, sendBuffer, 0, StringLen(preData));
    ArrayCopy(sendBuffer, fileData, StringLen(preData), 0, fileSize);
    StringToCharArray(postData, sendBuffer, StringLen(preData) + fileSize, StringLen(postData));
    
    // 导入ANSI版本的WinInet函数
    #import "Wininet.dll"
        int InternetOpenA(string lpszAgent, int dwAccessType, string lpszProxyName, string lpszProxyBypass, int dwFlags);
        int InternetConnectA(int hInternet, string lpszServerName, int nServerPort, string lpszUsername, string lpszPassword, int dwService, int dwFlags, int dwContext);
        int HttpOpenRequestA(int hConnect, string lpszVerb, string lpszObjectName, string lpszVersion, string lpszReferer, string lpszAcceptTypes, int dwFlags, int dwContext);
        bool HttpSendRequestA(int hRequest, string lpszHeaders, int dwHeadersLength, uchar &lpOptional[], int dwOptionalLength);
        bool InternetCloseHandle(int hInet);
        int HttpQueryInfoA(int hHttpRequest, int dwInfoLevel, string &lpBuffer, int &lpdwBufferLength, int &lpdwIndex);
    #import
    
    // 初始化WinInet连接
    int hOpen = InternetOpenA("MT4 Image Uploader", 1, "", "", 0);
    if(hOpen == 0)
    {
        Print("InternetOpenA失败,错误码:", GetLastError());
        return false;
    }
    
    int hConnect = InternetConnectA(hOpen, "localhost", 8080, "", "", 3, 0, 0);
    if(hConnect == 0)
    {
        Print("InternetConnectA失败,错误码:", GetLastError());
        InternetCloseHandle(hOpen);
        return false;
    }
    
    int hRequest = HttpOpenRequestA(hConnect, "POST", "/ConnectMT4/funcphp/screenpost.php", "HTTP/1.1", "", "", 0, 0);
    if(hRequest == 0)
    {
        Print("HttpOpenRequestA失败,错误码:", GetLastError());
        InternetCloseHandle(hConnect);
        InternetCloseHandle(hOpen);
        return false;
    }
    
    // 发送请求
    string headers = "Content-Type: multipart/form-data; boundary=" + boundary;
    bool sendResult = HttpSendRequestA(hRequest, headers, StringLen(headers), sendBuffer, totalSize);
    Print("上传请求发送结果:", sendResult);
    
    // 读取服务器响应(用于调试)
    if(sendResult)
    {
        string statusCode;
        int bufLen = 1024;
        HttpQueryInfoA(hRequest, 0x00000001, statusCode, bufLen, 0);
        Print("服务器状态码:", statusCode);
        
        uchar responseBuf[];
        ArrayResize(responseBuf, 1024);
        int bytesRead;
        while(InternetReadFile(hRequest, responseBuf, 1024, bytesRead) && bytesRead > 0)
        {
            Print("服务器响应:", CharArrayToString(responseBuf, 0, bytesRead));
            ArrayInitialize(responseBuf, 0);
        }
    }
    
    // 正确关闭句柄(顺序不能错)
    InternetCloseHandle(hRequest);
    InternetCloseHandle(hConnect);
    InternetCloseHandle(hOpen);
    
    return sendResult;
}

PHP端补充调试代码

修改你的PHP代码,增加错误排查信息,方便确认问题:

<?php
// 开启错误提示,调试阶段必备
error_reporting(E_ALL);
ini_set('display_errors', 1);

// 打印所有上传相关数据,直观排查问题
print_r($_FILES);
print_r($_POST);

if(isset($_FILES["uploadedfile"]) && $_FILES["uploadedfile"]["error"] == UPLOAD_ERR_OK) {
    echo "✅ 文件上传成功!文件名:" . $_FILES["uploadedfile"]["name"];
    // 可选:将临时文件移动到指定目录
    // move_uploaded_file($_FILES["uploadedfile"]["tmp_name"], "./uploads/" . $_FILES["uploadedfile"]["name"]);
} else {
    $errorCode = $_FILES["uploadedfile"]["error"] ?? "未知错误";
    echo "❌ 文件上传失败,错误码:" . $errorCode;
}
?>

额外调试建议

  1. 先确认服务器本身能接收文件:用Postman模拟一个multipart/form-data上传请求,测试PHP接口是否正常。
  2. 检查PHP配置:确保php.ini里的upload_max_filesize、post_max_size足够大,upload_tmp_dir有写入权限。
  3. 查看MT4日志:每个WinInet函数调用后,用GetLastError()打印错误码,定位连接/发送阶段的问题。

内容的提问来源于stack exchange,提问作者José López

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 04:03:11