I am trying to send a text file through POST to my upload.php form in php on my localhost webserver using C++.
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);
}
?>
The upload directory exists in the same directory as upload.php (contents above).
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;
}
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
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?
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 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.
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.
Change the allocation to this:
content = (char*) malloc (sizeof(char)*(lSize+1));
And after reading the contents of the file do this:
content[lSize] = '\0';
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);
Edit:
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);
Edit2:
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)
The boundary isn't setup correctly.
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
The HTTP header should be like this: Content-Type: multipart/form-data; boundary=BOUNDARY
So the sprintfs should look like this:
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.
To sum up:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With