0

I am new to C++ environment. I try to upload a image file to PHP server in C++. But it does not send the full file. Only I get uploaded image file size is 1 KB.

I got a post in SO like mine. But I don't know how to convert image binary to base64 string. I tried with another solution memcpy, it also doesn't work.

Upload file via POST

My C++ Code:

#define _CRT_SECURE_NO_DEPRECATE
#include <iostream>
#include <tchar.h>
#include <Urlmon.h>
#pragma comment (lib, "Urlmon.lib")

#include <windows.h>
#include <wininet.h>
#include <iostream>
#include <tchar.h>
#include <stdio.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 cv;
using namespace std;

int main()
{
    // Local variables
    static char *filename = "test.jpg";   //Filename to be loaded
    static char *filepath = "test.jpg";   //Filename to be loaded
    static char *type = "text/jpeg";
    static TCHAR hdrs[] = "Content-Type: multipart/form-data; boundary=---------------------------7d82751e2bc0858";
    static char boundary[] = "-----------------------------7d82751e2bc0858";            //Header boundary
    static char nameForm[] = "uploadedfile";     //Input form name
    static char iaddr[] = "server";        //IP address
    static char url[] = "uploader.php";

    char * buffer;                   //Buffer containing file + headers
    char * content;                  //Buffer containing file
    FILE * pFile;                    //File pointer
    long lSize;                      //File size
    size_t result;
    char *pos; // used in the loop

    // 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);
    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);

    rewind (pFile);

    if (result != lSize)
    {
        printf("ERROR_SIZE");
        getchar();
        return ERROR_OPEN_FILE;
    }
    printf("SIZE_OK\n");

    // 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(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, "%sContent-Length: %d\r\n", buffer, lSize);
    sprintf(buffer, "%s\r\n%s\r\n", buffer, content);

    /**
    sprintf(buffer, "%s\r\n", buffer);
    memcpy(buffer + strlen(buffer),content,lSize);
    sprintf(buffer, "%s\r\n", buffer);
    */
    sprintf(buffer, "%s%s--\r\n", buffer, boundary);

    //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");
    printf("\r\n%s\r\n",buffer);

    //close any valid internet-handles
    InternetCloseHandle(hSession);
    InternetCloseHandle(hConnect);
    InternetCloseHandle(hRequest);
}

Output:

OPEN_FILE
MEMORY_ALLOCATED     "44358" 
SIZE_OK
FILE_CLOSE
INTERNET_OPENED
INTERNET_CONNECTED
INTERNET_REQ_OPEN
INTERNET_SEND_OK


-----------------------------7d82751e2bc0858

Content-Disposition: form-data; name="uploadedfile"; filename="test.jpg"

Content-Type: text/jpeg



ÿØÿà

-----------------------------7d82751e2bc0858--

Thanks

Community
  • 1
  • 1
Iyyappan S
  • 61
  • 2
  • 10
  • Any reason for not using libcurl or something like that? – deviantfan Apr 22 '14 at 11:51
  • 1
    You're printing the content as if it were a string, that means that it will stop on the first 0. – jsantander Apr 22 '14 at 11:57
  • Also, you're sprinting always on the same place... you need to advance the buffer pointer – jsantander Apr 22 '14 at 12:00
  • Yeah i have found few libs over.. but i try to run this code.. my last option is third party library – Iyyappan S Apr 22 '14 at 12:00
  • hi jsantander.. how i print the advanced buffer pointer can u give me some sample code – Iyyappan S Apr 22 '14 at 12:01
  • Actually, I was wrong, you're printing always in the same place because you *re-print* always the previous contents. However this is not very efficient and if you're adding binary data (with memcpy), when you reprint the buffer it will again end at the first 0. – jsantander Apr 22 '14 at 12:15
  • Hi i have used memcpy with below it does not print binary. 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, "%sContent-Length: %d\r\n", buffer, lSize); sprintf(buffer, "%s\r\n", buffer); memcpy(buffer + strlen(buffer),content,lSize); sprintf(buffer, "%s\r\n", buffer); sprintf(buffer, "%s%s--\r\n", buffer, boundary); – Iyyappan S Apr 22 '14 at 12:27

1 Answers1

1

If you keep to the binary route

//allocate memory to contain the whole file + HEADER
buffer = (char*)malloc(sizeof(char)*lSize + 2048);
int chars=0;

//print header
chars+=sprintf(buffer+chars, "%s\r\nContent-Disposition: form-data; name=\"%s\"; filename=\"%s\"\r\n", boundary, nameForm, filename);
chars+=sprintf(buffer+chars, "Content-Type: %s\r\n", type);
chars+=sprintf(buffer+chars, "Content-Length: %d\r\n", lSize);

chars+=sprintf(buffer+chars, "\r\n");
memcpy(buffer + chars,content,lSize);
chars+=lSize;
chars+=sprintf(buffer+chars, "\r\n");

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

But in any case my recommendation is for your to look at any of the many libraries that exists that implements HTTP communication (libCURL is a good place to start)

Some additional notes:

instead of

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

do

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

as strlen(buffer) will stop at the first null character.

and Whent you're printing the result to std out, it will be treated as string.... and end with the first null.

jsantander
  • 4,972
  • 16
  • 27
  • Hi, I tried your code, but it print binary twice. ' -----------------------------7d82751e2bc0858 Content-Disposition: form-data; name="uploadedfile"; filename="test.jpg" Content-Type: text/jpeg Content-Length: 44358 ÿØÿà ÿØÿà' – Iyyappan S Apr 22 '14 at 12:19
  • Sorry... I was cut and pasting your version and uncommenting the memcopy part... but forgot to remove one sprintf.... check it now? – jsantander Apr 22 '14 at 12:30
  • it does not print the end boundary to buffer. Image binary also same value ÿØÿà. it does not read the full file. – Iyyappan S Apr 22 '14 at 12:37
  • @IyyappanS That's because of the `printf("\r\n%s\r\n",buffer);` you're printing the buffer as a string that stops at the first 0. – jsantander Apr 22 '14 at 13:07
  • ok I understand.. but i didn't found uploaded file on the server – Iyyappan S Apr 22 '14 at 13:11
  • @IyyappanS check the length in the HttpSendRequest (see my edit to the answer). – jsantander Apr 22 '14 at 18:30
  • @jsantander- Thank you very much for your answer.Am wasted few days to run this script.. – Iyyappan S Apr 23 '14 at 06:44