【问题标题】:Upload Image File in C++在 C++ 中上传图像文件
【发布时间】:2014-04-22 11:47:20
【问题描述】:

我是 C++ 环境的新手。我尝试将图像文件上传到 C++ 中的 PHP 服务器。但它不会发送完整的文件。只有我上传的图像文件大小为 1 KB。

我在 SO 中找到了一个和我一样的帖子。但我不知道如何将图像二进制转换为 base64 字符串。我尝试了另一种解决方案 memcpy,它也不起作用。

Upload file via POST

我的 C++ 代码:

#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);
}

输出:

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--

谢谢

【问题讨论】:

  • 有什么理由不使用 libcurl 或类似的东西?
  • 你打印的内容好像它是一个字符串,这意味着它将在第一个 0 处停止。
  • 另外,你总是在同一个地方冲刺......你需要推进缓冲区指针
  • 是的,我找到了几个库。但我尝试运行这段代码。我的最后一个选择是第三方库
  • 嗨 jsantander.. 我如何打印高级缓冲区指针你能给我一些示例代码

标签: c++ file-upload http-post


【解决方案1】:

如果你坚持二元路线

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

但无论如何,我的建议是让您查看现有的许多实现 HTTP 通信的库中的任何一个(libCURL 是一个很好的起点)

一些补充说明:

而不是

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

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

因为 strlen(buffer) 将在第一个空字符处停止。

当您将结果打印到标准输出时,它将被视为字符串......并以第一个 null 结尾。

【讨论】:

  • 嗨,我试过你的代码,但它打印了两次二进制文件。 ' -----------------------------7d82751e2bc0858 内容处置:表单数据;名称="上传文件"; filename="test.jpg" 内容类型:文本/jpeg 内容长度:44358 ÿØÿà ÿØÿà'
  • 对不起...我被剪切并粘贴了您的版本并取消了 memcopy 部分的注释...但忘记删除一个 sprintf...。现在检查吗?
  • 它不会将结束边界打印到缓冲区。图像二进制也相同的值ÿØÿà。它不会读取完整的文件。
  • @IyyappanS 这是因为 printf("\r\n%s\r\n",buffer); 您将缓冲区打印为在第一个 0 处停止的字符串。
  • 好的我明白了.. 但是我没有在服务器上找到上传的文件
猜你喜欢
  • 2016-08-25
  • 2011-06-13
  • 2012-05-14
  • 2020-04-01
  • 1970-01-01
  • 1970-01-01
  • 2013-01-08
  • 2011-03-21
  • 1970-01-01
相关资源
最近更新 更多