发送文件POST C ++ [英] Send file POST C++

查看:96
本文介绍了发送文件POST C ++的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用C ++通过POST将文本文件发送到我的localhost网络服务器上的php中的upload.php表单。

I am trying to send a text file through POST to my upload.php form in php on my localhost webserver using C++.

这是我的php代码要求:

Here is my php code for the request:

<?php
$uploaddir = 'upload/';

if (is_uploaded_file(isset($_FILES['file']['tmp_name'])?($_FILES['file'['tmp_name']):0)) 
{
    $uploadfile = $uploaddir . basename($_FILES['file']['name']);
    echo "File ". $_FILES['file']['name'] ." uploaded successfully. ";

    if (move_uploaded_file($_FILES['file']['tmp_name'], $uploadfile)) 
    {
        echo "File was moved! ";
    }
    else
    {
        print_r($_FILES);
    }
}
else 
{
    print_r($_FILES);
}
?>

upload 目录存在于同一目录中as upload.php(上面的内容)。

The upload directory exists in the same directory as upload.php (contents above).

这是我用来准备http请求并发送它的代码:

Here is the code which I am using to prepare the http request and send it:

#include <windows.h>
#include <wininet.h>
#include <iostream>
#include <tchar.h>

#pragma comment(lib,"wininet.lib")
#define ERROR_OPEN_FILE       10
#define ERROR_MEMORY          11
#define ERROR_SIZE            12
#define ERROR_INTERNET_OPEN   13
#define ERROR_INTERNET_CONN   14
#define ERROR_INTERNET_REQ    15
#define ERROR_INTERNET_SEND   16

using namespace std;

int main()
{
 // Local variables
 static char *filename   = "test.txt";   //Filename to be loaded
 static char *filepath   = "C:\\wamp\\www\\post\\test.txt";   //Filename to be loaded
 static char *type       = "text/plain";
 static char boundary[]  = "--BOUNDARY---";            //Header boundary
 static char nameForm[]  = "file";     //Input form name
 static char iaddr[]     = "localhost";        //IP address
 static char url[]       = "/post/upload.php";         //URL

 char hdrs[512]={'-'};                  //Headers
 char * buffer;                   //Buffer containing file + headers
 char * content;                  //Buffer containing file
 FILE * pFile;                    //File pointer
 long lSize;                      //File size
 size_t result;                   

 // Open file
 pFile = fopen ( filepath , "rb" );
 if (pFile==NULL) 
 {
     printf("ERROR_OPEN_FILE");
     getchar();
     return ERROR_OPEN_FILE;
 }
 printf("OPEN_FILE\n");

 // obtain file size:
 fseek (pFile , 0 , SEEK_END);
 lSize = ftell (pFile);
 rewind (pFile);

 // allocate memory to contain the whole file:
 content = (char*) malloc (sizeof(char)*(lSize+1));
 if (content == NULL) 
 {
     printf("ERROR_MEMORY");
     getchar();
     return ERROR_OPEN_FILE;
 }
 printf("MEMORY_ALLOCATED\t \"%d\" \n",&lSize);
 // copy the file into the buffer:
 result = fread (content,1,lSize,pFile);
 if (result != lSize) 
 {
     printf("ERROR_SIZE");
     getchar();
     return ERROR_OPEN_FILE;
 }
 printf("SIZE_OK\n");

 content[lSize] = '\0';

 // terminate
 fclose (pFile);
 printf("FILE_CLOSE\n");
 //allocate memory to contain the whole file + HEADER
 buffer = (char*) malloc (sizeof(char)*lSize + 2048);

 //print header
 sprintf(hdrs,"Content-Type: multipart/form-data; boundary=%s",boundary);
 sprintf(buffer,"%s\r\nContent-Disposition: form-data; name=\"%s\"; filename=\"%s\"\r\n",boundary,nameForm,filename);
 sprintf(buffer,"%sContent-Type: %s\r\n",buffer,type);
 sprintf(buffer,"%s\r\n%s",buffer,content);
 sprintf(buffer,"%s\r\n--%s--\r\n",buffer,boundary);

 printf("%s", buffer);

 //Open internet connection
 HINTERNET hSession = InternetOpen("WINDOWS",INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
 if(hSession==NULL) 
 {
     printf("ERROR_INTERNET_OPEN");
     getchar();
     return ERROR_OPEN_FILE;
 }
 printf("INTERNET_OPENED\n");

 HINTERNET hConnect = InternetConnect(hSession, iaddr,INTERNET_DEFAULT_HTTP_PORT, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 1);
 if(hConnect==NULL) 
 {
     printf("ERROR_INTERNET_CONN");
     getchar();
     return ERROR_INTERNET_CONN;
 }
 printf("INTERNET_CONNECTED\n");

 HINTERNET hRequest = HttpOpenRequest(hConnect, (const char*)"POST",_T(url),NULL, NULL, NULL,INTERNET_FLAG_RELOAD, 1);
 if(hRequest==NULL) 
  {
     printf("ERROR_INTERNET_REQ");
     getchar();

 }
 printf("INTERNET_REQ_OPEN\n");

 BOOL sent= HttpSendRequest(hRequest, hdrs, strlen(hdrs), buffer, strlen(buffer));

 if(!sent) 
 {
     printf("ERROR_INTERNET_SEND");
     getchar();
     return ERROR_INTERNET_CONN;
 }
 printf("INTERNET_SEND_OK\n");

 InternetCloseHandle(hSession);
 InternetCloseHandle(hConnect);
 InternetCloseHandle(hRequest);

 getchar();
 return 0;
}

当我执行upload.exe(上面的内容)时。我得到以下输出:

When I execute the upload.exe (contents above). I get the following output:

OPEN_FILE
MEMORY_ALLOCATED    "1832340"
SIZE_OK
FILE_CLOSE
---BOUNDARY---
Content Disposition: form-data; name="file"; filename="test.txt"
Content-Type: text/plain
test
---BOUNDARY---
INTERNET_OPENED
INTERNET_CONNECTED
INTERNET_REQ_OPEN
INTERNET_SEND_OK

以下是PHP错误日志:

Here is the PHP error log:

[12-Nov-2014 20:09:58 Europe/Paris] PHP Stack trace:
[12-Nov-2014 20:09:58 Europe/Paris] PHP   1. {main}() C:\wamp\www\post\upload.php:0

我对这意味着什么感到困惑。这是一个错误吗?

I'm a little confused as to what this means. Is this an error?

看来一切顺利(注意:test.txt的内容是test)。当我查看 upload 目录时。 test.txt文件不在那里。该目录为空。任何人都可以帮我理解问题所在吗?谢谢!

It appears everything goes through (note: the contents of test.txt are "test"). Though when I look in the upload directory. The test.txt file is not in there. The directory is empty. Can anyone help me understand what the problem is? Thank-you!

BUMP 没有人知道怎么做或者不可能吗?因为如果不可能那么就告诉我这样我就可以不再浪费时间去搜索了。

BUMP Does no one know how to do this or is it no possible? Because if it's not possible then just tell me so I can stop wasting my time searching.

推荐答案

测试你的c ++客户端我发现包含文件内容的变量 content 不以 NULL 结尾,所以当你用<复制它时code> sprintf 您正在复制随机字节,直到出现 NULL

Testing your c++ client I found that the variable content which contains the content of the file doesn't end with a NULL so when you copy it with sprintf you are copying random bytes until a NULL appears.

将分配更改为:

 content = (char*) malloc (sizeof(char)*(lSize+1));

在阅读文件内容后,请执行以下操作:

And after reading the contents of the file do this:

content[lSize] = '\0';

另外,我很确定 BOUNDARY 应该从新的一行开始。所以也做这个改变:

Also, I am quite sure that the BOUNDARY should start at a new line. So make this change too:

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

修改:

通过比较常规的HTML表单请求,我可以看到内容应该在两行之后开始,所以也要更改它:

By comparing a regular HTML form request, I can see that the content should start after two lines, so change this too:

sprintf(buffer,"%s\r\n%s",buffer,content);

编辑2:

使用PHP代码测试后,我发现了一些c ++代码的问题。
(顺便说一下,PHP代码中有一个拼写错误:在if语句中缺少]

After testing with the PHP code, I found some more problems with the c++ code. (btw, there is a typo in the PHP code: missing ] in the if statement)

边界设置不正确。

mime的格式应如下所示:

The format of the mime should be like this:

--BOUNDARY
Content-Disposition: form-data; name="file"; filename="test2.txt"
Content-Type: text/plain

test
--BOUNDARY

HTTP标头应如下所示:
Content-Type:multipart / form-data; boundary = BOUNDARY

The HTTP header should be like this: Content-Type: multipart/form-data; boundary=BOUNDARY

所以 sprintf s应如下所示:

sprintf(hdrs,"Content-Type: multipart/form-data; boundary=%s",boundary);
sprintf(buffer,"--%s\r\nContent-Disposition: form-data; name=\"%s\"; filename=\"%s\"\r\n",boundary,nameForm,filename);
sprintf(buffer,"%sContent-Type: %s\r\n",buffer,type);
sprintf(buffer,"%s\r\n%s",buffer,content);
sprintf(buffer,"%s\r\n--%s\r\n",buffer,boundary);

在完成本文中的所有修复后,代码应该可以正常工作。

After doing all of the fixes in this post, the code should work.

总结:


  1. 我建议使用VM设置更容易调试这类问题因为那时你可以使用Wireshark \Fidler \ Burp。 (您也可以尝试为localhost配置代理,我自己也没试过。也可以尝试使用外部Internet IP并配置路由器进行端口转发,但这对于这类任务来说太复杂了。)

  2. 如果这没有帮助,NetCat可能会有所帮助。不是那么容易和友好,而是完成工作。

  3. 简单地将工作示例与您的请求输出进行比较可以准确显示缺少的内容。我为此使用了Beyond Compare。总是使用比较软件,因为人眼很容易被欺骗。

  4. 最明显的是阅读Mime规范并确切地看到缺少的东西。

  1. I would recommend using a VM setup to debug these kind of problems more easily because then you can use Wireshark\Fidler\Burp. (You can also try configuring proxy for localhost as well, never tried that myself. Also you can try using your external Internet IP and configure your router for port forwarding, but that's too complicated for this kind of task).
  2. If that doesn't help, NetCat may help. Not as easy and friendly, but does the job.
  3. Simply comparing a working example with your request output shows exactly what is missing. I used Beyond Compare for this. Always work with a comparing software since the human eye can be tricked easily.
  4. The most obvious was to read the Mime specification and see exactly what is missing.

这篇关于发送文件POST C ++的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆