发送文件POST C ++ [英] Send file 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.
总结:
- 我建议使用VM设置更容易调试这类问题因为那时你可以使用Wireshark \Fidler \ Burp。 (您也可以尝试为localhost配置代理,我自己也没试过。也可以尝试使用外部Internet IP并配置路由器进行端口转发,但这对于这类任务来说太复杂了。)
- 如果这没有帮助,NetCat可能会有所帮助。不是那么容易和友好,而是完成工作。
- 简单地将工作示例与您的请求输出进行比较可以准确显示缺少的内容。我为此使用了Beyond Compare。总是使用比较软件,因为人眼很容易被欺骗。
- 最明显的是阅读Mime规范并确切地看到缺少的东西。
- 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).
- If that doesn't help, NetCat may help. Not as easy and friendly, but does the job.
- 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.
- The most obvious was to read the Mime specification and see exactly what is missing.
这篇关于发送文件POST C ++的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!