Dev C++ Wininet Загрузить файл с помощью HTTP

Я хочу загрузить «C:\test.txt» на веб-сервер, когда я запускаю программу, файл не загружается, и я не получаю никаких ошибок.

полный код C++ можно найти здесь

и код 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;
}

person student    schedule 31.12.2009    source источник
comment
Вы установили fiddler и видели, какой HTTP-трафик отправляется? Я бы начал там в первую очередь.   -  person Alan    schedule 31.12.2009
comment
Когда я редактировал исходный код, я получил сообщение об ошибке Ошибка: HttpSendRequest 12005, см. гиперссылку выше.   -  person student    schedule 31.12.2009


Ответы (3)


Я смог заставить ваш код работать.

Прежде всего, код по предоставленной вами ссылке и код, который вы разместили, не совпадают:

InternetConnect(hSession, _T("localhost"), ...
InternetConnect(hSession, _T("http://student114.110mb.com"), ...

Вы должны передать здесь имя хоста или IP-адрес, поэтому «localhost» подходит, но «http://student114.110mb.com" нет. При передаче URL-адреса вы получите код ошибки 12005 [см. коды ошибок WinINet на msdn].

Другая проблема — строка frmdata. Вы должны удвоить обратную косую черту в C:\test.txt, иначе вы получите символ табуляции \t в своей строке. \n до и после разделителей также следует заменить на \r\n, потому что RFC 1521 и большинство других интернет-протоколов используют 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» обычно соответствует имени тега ‹input type="file"› в HTML, но в вашем случае оно указано в параметре name= строки frmdata[].

Вот код PHP, который я использовал для проверки этого

move_uploaded_file($_FILES["uploadedfile"]["tmp_name"], "/files/my_file");

Когда вы работаете над таким сложным взаимодействием клиент/сервер, полезно тестировать каждую часть отдельно. Вы могли бы, например.

  • Напишите простую форму загрузки HTML для проверки вашего php-скрипта.

  • Пусть ваша программа отправит свой запрос в netcat и проверит вывод.

person Alex Jasmin    schedule 31.12.2009

вам нужно отправить полный запрос без WinAPI, если вы хотите получить хороший запрос на загрузку файла через php-скрипт.

В прошлом я тоже пытался отправить такой запрос, как вы, со всеми функциями апи. Но когда я обнюхал его с помощью 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. Извините за мой плохой английский, это не мой родной язык

person Patrone    schedule 31.03.2010

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";
person Arko    schedule 09.01.2015