我想将“C:\ test.txt”上传到网络服务器,当我运行程序时,文件没有上传,我没有收到任何错误。
the complete C++ code can be find here
和webserver上的php代码可以在这里找到:“http://student114.110mb.com/upload.txt” 要么 “http://student114.110mb.com/upload.php”
在我做错的地方帮助我
#include <windows.h>
#include <wininet.h>
#include <tchar.h>
#include <iostream>
#pragma comment(lib,"wininet.lib")
using namespace std;
int main()
{
static TCHAR frmdata[] = "-----------------------------7d82751e2bc0858\nContent-Disposition: form-data; name=\"uploadedfile\"; filename=\"C:\test.txt\"\nContent-Type: text/plain\n\nfile contents here\n-----------------------------7d82751e2bc0858--";
static TCHAR hdrs[] = "Content-Type: multipart/form-data; boundary=---------------------------7d82751e2bc0858";
HINTERNET hSession = InternetOpen("MyAgent",INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
if(hSession==NULL)
{
cout<<"Error: InternetOpen";
}
HINTERNET hConnect = InternetConnect(hSession, _T("localhost"),INTERNET_DEFAULT_HTTP_PORT, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 1);
if(hConnect==NULL)
{
cout<<"Error: InternetConnect";
}
HINTERNET hRequest = HttpOpenRequest(hConnect, (const char*)"POST",_T("upload.php"), NULL, NULL, (const char**)"*/*\0", 0, 1);
if(hRequest==NULL)
{
cout<<"Error: HttpOpenRequest";
}
BOOL sent= HttpSendRequest(hRequest, hdrs, strlen(hdrs), frmdata, strlen(frmdata));
if(!sent)
{
cout<<"Error: HttpSendRequest";
}
//close any valid internet-handles
InternetCloseHandle(hSession);
InternetCloseHandle(hConnect);
InternetCloseHandle(hRequest);
return 0;
}
答案 0 :(得分:5)
我能够使您的代码正常工作。
首先,您提供的链接上的代码和您发布的代码不一样:
InternetConnect(hSession, _T("localhost"), ...
InternetConnect(hSession, _T("http://student114.110mb.com"), ...
您必须在此处传递主机名或IP地址,以便“localhost”良好,但“http://student114.110mb.com”不是。 如果您传递了网址,则会收到12005错误代码[see WinINet error codes on msdn]。
另一个问题是frmdata字符串。您应该在C:\ test.txt中加倍反斜杠,否则您将在字符串中得到制表符\ t。分隔符之前和之后的\ n也应该由\ r \ n替换,因为RFC 1521和大多数其他Internet协议使用CRLF作为行分隔符。
这是我用过的字符串。
static TCHAR frmdata[] = "-----------------------------7d82751e2bc0858\r\nContent-Disposition: form-data; name=\"uploadedfile\"; filename=\"C:\\test.txt\"\r\nContent-Type: text/plain\r\n\r\nfile contents here\r\n-----------------------------7d82751e2bc0858--\r\n";
最后,PHP代码不起作用,因为您使用$ _FILES [“file”],您应该使用$ _FILES [“uploadedfile”]。 “uploadedfile”通常对应于&lt; input type =“file”&gt;的名称。 HTML中的标记,但在您的情况下,它在frmdata []字符串的 name = 参数中指定。
这是我用来测试这个
的PHP代码move_uploaded_file($_FILES["uploadedfile"]["tmp_name"], "/files/my_file");
当您处理复杂的客户端/服务器交互时,这有助于分别测试每个部分。你可以举个例子。
写一个简单的HTML上传表单 测试你的PHP脚本
让您的程序发送请求 netcat并检查输出
答案 1 :(得分:2)
如果您想要通过php脚本上传文件的良好请求,则必须在没有WinAPI的情况下发送完整请求。
在过去,我也试图像你一样发送所有api函数的请求。 但是当我用wireshark嗅探它时,我得到了和你一样的解决方案:标题被合并而且它不起作用。
所以我再次使用了winsock,如果您要发送的数据不是太大,它就会起作用。
这是代码:
#include <iostream>
#include <winsock2.h>
#include <string>
using namespace std;
//link libwsock32.a
unsigned long WinsockStart()
{
WSADATA wsa;
unsigned long ulong;
struct hostent *host;
if(WSAStartup(MAKEWORD(2,2), &wsa) < 0)
{
cout << "Error WinsockStart()" << endl;
WSACleanup();
return 1;
}
if((host=gethostbyname("www.example.com"))<0)
{
cout << "Fehler gethostbyname()" << endl;
WSACleanup();
return 2;
}
ulong = *(unsigned long*) host->h_addr;
return ulong;
}
void error_exit(string text)
{
cout << text;
WSACleanup();
exit(EXIT_FAILURE);
}
int main()
{
SOCKET sock;
struct sockaddr_in addr;
unsigned long win=0;
int con = 0, gr=0, send_r=0, rec=0;
char header[2048], puffer[2018];
string to_send="hello world";
string name="test99.txt";
win=WinsockStart();
if(win==1||win==2)
error_exit("Error WinsockStart()");
addr.sin_family=AF_INET;
addr.sin_port=htons(80);
addr.sin_addr.s_addr = win;
sock = socket(AF_INET, SOCK_STREAM, 0);
if(sock<0)
error_exit("Error socket()");
gr = (to_send.size()+name.size()+287);
sprintf(header, "POST /upload.php HTTP/1.1\r\n");
sprintf(header, "%sHost: www.example.com\r\n", header);
sprintf(header, "%sConnection: Keep-Alive\r\n", header);
sprintf(header, "%sContent-Type: multipart/form-data; boundary=---------------------------90721038027008\r\n", header);
sprintf(header, "%sContent-Length: %d\r\n", header, gr);
sprintf(header, "%s\r\n", header);
sprintf(header, "%s-----------------------------90721038027008\r\n", header);
sprintf(header, "%sContent-Disposition: form-data; name=\"upfile\"; filename=\"%s\"\r\n", header, name.c_str());
sprintf(header, "%sContent-Type: text/plain\r\n", header);
sprintf(header, "%s\r\n", header);
sprintf(header, "%s%s\r\n", header, to_send.c_str());
sprintf(header, "%s-----------------------------90721038027008\r\n", header);
sprintf(header, "%sContent-Disposition: form-data; name=\"post\"\r\n", header);
sprintf(header, "%s\r\n", header);
sprintf(header, "%supload\r\n\r\n", header);
sprintf(header, "%s-----------------------------90721038027008--\r\n\r\n\0", header);
con = connect(sock, (SOCKADDR*)&addr, sizeof(addr));
if(con < 0)
error_exit("Error connect()");
if(send_r=send(sock, header, strlen(header), 0)<0)
error_exit("Error send()");
while(rec=recv(sock, puffer, 2048, 0))
{
if(rec==0)
error_exit("Server quit");
printf("%s", puffer);
}
closesocket(sock);
WSACleanup();
return EXIT_SUCCESS;
}
到目前为止,我已经搜索过,并且我尝试过使用WinHttpAPI的其他解决方案,但我没有找到任何符合我目的的内容。
帕特罗
P.S。抱歉我的英文不好,这不是我的母语
答案 2 :(得分:1)
static TCHAR frmdata[] = "-----------------------------7d82751e2bc0858\r\nContent-Disposition: form-data; name=\"uploadedfile\"; filename=\"C:\\test.txt\"\r\nContent-Type: text/plain\r\n\r\nfile contents here\r\n-----------------------------7d82751e2bc0858--\r\n";
最后“ - ”字符应位于“----------------------------- 7d82751e2bc0858”边界之前,而不是之后
正确的代码:
static TCHAR frmdata[] = "-----------------------------7d82751e2bc0858\r\nContent-Disposition: form-data; name=\"uploadedfile\"; filename=\"C:\\test.txt\"\r\nContent-Type: text/plain\r\n\r\nfile contents here\r\n-------------------------------7d82751e2bc0858\r\n";