2014-09-27 38 views
1
#include <winsock2.h> 
#include <windows.h> 
#include <iostream> 
#pragma comment(lib,"ws2_32.lib") 
using namespace std; 
int main(){ 
    WSADATA wsaData; 
    if (WSAStartup(MAKEWORD(2,2), &wsaData) != 0) { 
     cout << "WSAStartup failed.\n"; 
     system("pause"); 
     return 1; 
    } 
    SOCKET Socket=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP); 
    struct hostent *host; 
    host = gethostbyname("127.0.0.1"); 
    SOCKADDR_IN SockAddr; 
    SockAddr.sin_port=htons(80); 
    SockAddr.sin_family=AF_INET; 
    SockAddr.sin_addr.s_addr = *((unsigned long*)host->h_addr); 
    cout << "Connecting...\n"; 
    if(connect(Socket,(SOCKADDR*)(&SockAddr),sizeof(SockAddr)) != 0){ 
     cout << "Could not connect"; 
     system("pause"); 
     return 1; 
    } 
    cout << "Connected.\n"; 



      char header[]="POST /xampp/tests/file/check.php HTTP/1.1\r\n" 
       "Host: 127.0.0.1\r\n" 
       "Content-Type: application/x-www-form-urlencoded\r\n" 
       "Content-Length: 10\r\n" 
       "Connection: close\r\n" 
       "\r\n" 
       "text1=sase"; 
    send(Socket,header, strlen(header),0); 
    char buffer[100000]; 
    int nDataLength; 
    while ((nDataLength = recv(Socket,buffer,100000,0)) > 0){   
     int i = 0; 
     while (buffer[i] >= 32 || buffer[i] == '\n' || buffer[i] == '\r') { 
      cout << buffer[i]; 
      i += 1; 
     } 
    } 
    closesocket(Socket); 
     WSACleanup(); 
     cout<<endl<<endl; 
    system("pause"); 
    return 0; 
} 

这是我当前的代码。它发送text1,但现在我想要它发送一个文件(位于:C:\ Users \ Wade \ Downloads \ Documents)。我该怎么做 如何使用HTTP POST协议将用户的文件发送到服务器使用C++发送使用http POST的文件

+1

如果你成功地发送文字,是什么阻止你转换文件为文本(二进制模式),并把它以同样的方式?我的意思是 - 你已经完成了_hard_部分,现在是时候去做标准的事情 - 阅读文件了。 – 2014-09-27 03:12:15

+0

任何你不使用libcurl的原因,http://curl.haxx.se/。它旨在完成您想要的功能,并且是一款非常强大,成熟的产品。 – dgnuff 2014-09-27 03:39:25

回答

4

application/x-www-form-urlencoded只支持name=value对。要POST一个文件,你必须要么:

  1. 使用multipart/form-data代替。

    char *header="POST /xampp/tests/file/check.php HTTP/1.1\r\n" 
         "Host: 127.0.0.1\r\n" 
         "Content-Type: multipart/form-data; boundary=myboundary\r\n" 
         "Connection: close\r\n" 
         "\r\n" 
         "--myboundary\r\n" 
         "Content-Type: application/octet-stream\r\n" 
         "Content-Disposition: form-data; name=\"myfile\"; filename=\"myfile.ext\"\r\n" 
         "Content-Transfer-Encoding: 8bit\r\n" 
         "\r\n"; 
    send(Socket,header, strlen(header),0); 
    
    // send the raw file bytes here... 
    
    char *footer = "\r\n" 
          "--myboundary--\r\n"; 
    send(Socket, footer, strlen(footer), 0); 
    
  2. 通过自身发送文件的内容作为整个POST内容,设置Content-Type到的实际类型的文件或application/octet-stream的,并设置Content-Length到文件的大小。

    char *header="POST /xampp/tests/file/check.php HTTP/1.1\r\n" 
         "Host: 127.0.0.1\r\n" 
         "Content-Type: application/octet-stream\r\n" 
         "Content-Length: ...\r\n" // <-- substitute with the actual file size 
         "Connection: close\r\n" 
         "\r\n"; 
    send(Socket,header, strlen(header),0); 
    
    // send the raw file bytes here... 
    

你使用哪一个取决于什么服务器是能够接受的。

+0

我如何发送原始文件字节? – TheTherminator 2014-09-27 04:09:29

+0

打开文件(['CreateFile()'](http://msdn.microsoft.com/en-us/library/windows/desktop/aa363858.aspx)或['fopen()'](http:// msdn.microsoft.com/en-us/library/yeby3zcb.aspx))并循环读取其数据(['ReadFile()'](http://msdn.microsoft.com/zh-cn/library/windows /desktop/aa365467.aspx)或['fread()'](http://msdn.microsoft.com/zh-cn/library/kt0etdcs.aspx))转换为一个固定大小的缓冲区,在每次循环迭代中,直到你到达EOF。或者使用['TransmitFile()'](http://msdn.microsoft.com/en-us/library/windows/desktop/ms740565.aspx)。 – 2014-09-27 04:29:07

+0

我注意到'multipart/form-data'没有'Content-Length'是有意的 – TheTherminator 2014-09-27 06:17:06

0

我去工作。这里是没有读取文件的代码。

char outtemp[]; 
    ifstream inFile("c:\\temp.html"); 
    ofstream outtemp("temp"); 
    while(inFile.good()){ 
          getline(inFile,buffer); 
          outtemp<<buffer; 
          } 
    inFile.close();//close files after using 
    outtemp.close();//close files after using 




    char data[]= 
    "\r\n" 
    "--border287032381131322\r\n" 
    "Content-Disposition: form-data; name=\"this\" \r\n\r\n" 
    "aasda\r\n\r\n" 
    "--border287032381131322\r\n" 
    "Content-Disposition: form-data; name=\"file\"; filename=\"C:\\temp.html\" Content-Type: text/plain \r\n\r\n" 
char data2[]= 
    "<h1>Home page on main server</h1>\r\n\r\n" 
    "--border287032381131322--\r\n"; 

    char header[] = 
    "POST /xampp/tests/winsock_test/do.php HTTP/1.1\r\n" 
    "Host: 127.0.0.1\r\n" 
    "Content-Type: multipart/form-data; boundary=border287032381131322\r\n" 
    "Connection: close\r\n"; 
    strcat(header,data1); 
strcat(header,outtemp); 
strcat(header,data2) 
    cout<<"----------Sending----------------"<<endl<<header<<endl<<"size:"<<sizeof(data)<<endl<<"--------------sending end------------"<<endl<<endl;// for debug 

    send(Socket,header, strlen(header),0); 
+0

你不需要'multipart/form-data'的'Content-Length','filename'属性不应该包含路径信息,只包含文件名。无论如何,这并不能回答你原来的问题,因为你特别提出了如何从用户的文件系统发送文件,而这段代码并没有这样做。 – 2014-09-27 15:30:12

1

使用此代码

#define DATA_SIZE 1024*1024*10 //10MB 
#define MAXLINE 409600 

char * servIP = "127.0.0.1"; 
int servPort = 80; 

ssize_t send_file(char *fileDir, char *filename) 
{ 
    char *packet; 
    char pre_body[1024], post_body[1024]; 
    char sendline[MAXLINE + 1]; 
    char boundary[] ="----WebKitFormBoundaryu8FzpUGNDgydoA4z"; 

    char *bodyline = calloc(sizeof(char), DATA_SIZE); 
    char *fileBuf = calloc(sizeof(char), DATA_SIZE); 
    int sock = makeSocket(); 

    printf("send file name : %s\n", filename); 

    FILE *fp = fopen(fileDir, "r"); 
    if(fp == NULL){ 
     printf("file can't read\n"); 
     fclose(fp); 
     return -1; 
    } 

    fseek(fp, 0, SEEK_END); 
    int file_size = ftell(fp); 
    fseek(fp, 0, SEEK_SET); 
    if(fread(fileBuf, 1, file_size, fp) == -1){ 
     printf("fread error\n"); 
    } 
    // make body 
    sprintf(pre_body, "--%s\r\nContent-Disposition: form-data; name=\"pdata\"\r\n\r\n" 
     "%s\r\n--%s\r\nContent-Disposition: form-data; name=\"flag\"\r\n\r\n" 
     "%s\r\n--%s\r\nContent-Disposition: form-data; name=\"upfile\";filename=\"%s\"\r\n" 
     "Content-Type:application/octect-stream\r\n\r\n" 
     , boundary, "postdata", boundary,"no", boundary, filename); 

    sprintf(post_body, "\r\n--%s--\r\n", boundary); 

    int pre_len = strlen(pre_body); 
    int post_len = strlen(post_body); 
    int body_len = pre_len + file_size + post_len; 

    memcpy(bodyline, pre_body, pre_len); 
    memcpy(bodyline+pre_len, fileBuf, file_size); 
    memcpy(bodyline+pre_len+file_size, post_body, post_len); 

    //make header 
    sprintf(sendline, "POST /FileUpload.jsp HTTP/1.1\r\n" 
     "Host: %s\r\nConnection: keep-alive\r\n" 
     "Content-Length: %d\r\n" 
     "Content-Type: multipart/form-data; boundary=%s\r\n\r\n", servIP, body_len, boundary); 
    int head_len = strlen(sendline); 
    int packet_len = head_len+body_len; 

    //join header + body 
    packet=calloc(1, head_len+body_len+1); 
    memcpy(packet, sendline, head_len); 
    memcpy(packet+head_len, bodyline, body_len); 


    write(sock, packet, packet_len); 

    fclose(fp); 
    free(packet); 
    close(sock); 
    return 0; 
} 

int makeSocket(){ 
    struct sockaddr_in servAddr; 
    int sock; 
    char ip[20]; 
    /* Create areliable, stream socket using TCP */ 
    if((sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) 
     printf("socket create failed\n"); 

    struct hostent *host_entry; 
    host_entry = gethostbyname(servIP); 
    for(ndx = 0; NULL != host_entry->h_addr_list[ndx]; ndx++){ 
     strcpy(ip, inet_ntoa(*(struct in_addr*)host_entry->h_addr_list[ndx])); 
    } 

    memset(&servAddr, 0, sizeof(servAddr)); //Zero ou structure 
    servAddr.sin_family = AF_INET; //Internet address family 
    servAddr.sin_addr.s_addr = inet_addr(ip); //Server IP address 
    servAddr.sin_port = htons(servPort);//Server port 

    /* Establish the connection to the web server */ 
    if(connect(sock, (struct sockaddr *) &servAddr, sizeof(servAddr)) < 0) 
      printf("connet() failed\n"); 

    return sock; 
} 
+1

请提供一些描述以指出可能出错的地方。它将帮助人们了解什么是错误,并帮助他们学习,而不仅仅是提供代码。 – VPK 2017-03-07 07:45:07

+0

其他代码对我来说失败了,这一个做了窍门,我认为“Content-Length”是需要的。 – Entretoize 2017-09-21 06:40:19

相关问题