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; } ?>
额外调试建议
- 先确认服务器本身能接收文件:用Postman模拟一个multipart/form-data上传请求,测试PHP接口是否正常。
- 检查PHP配置:确保
php.ini里的upload_max_filesize、post_max_size足够大,upload_tmp_dir有写入权限。 - 查看MT4日志:每个WinInet函数调用后,用
GetLastError()打印错误码,定位连接/发送阶段的问题。
内容的提问来源于stack exchange,提问作者José López
相关产品推荐
相关产品推荐

