【问题标题】:How to upload a file to anonfile using wininet api in C?如何在 C 中使用 wininet api 将文件上传到 anonfile?
【发布时间】:2020-03-07 17:02:35
【问题描述】:

我正在尝试使用 wininet 库将文件上传到 C 中的 anonfile。

根据their API,我们需要发送一个指定文件的POST HTTP请求到以下URL:

https://api.anonfile.com/upload

另外,我上传了一个带有 CURL 的文件以查看生成的标题:https://pastebin.com/VZfhaxEy

因此,我的函数看起来像这个 (based on this post)。请注意,它仍然不处理服务器响应,只是发送:

#include <windows.h>
#include <wininet.h>
#include <stdio.h>

#pragma comment(lib,"Wininet.lib") //Library
#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

int main(int argc, char* argv[])
{
    // Local variables
    char* filename = "C:\\test.zip";   //Filename to be loaded
    char* type = "binary";
    char boundary[] = "pippo";            //Header boundary
    char nameForm[] = "upload";     //Input form name
    char iaddr[] = "api.anonfile.com";        //IP address
    char url[] = "upload";         //URL

    char hdrs[1024];                  //Headers
    char* buffer;                   //Buffer containing file + headers
    char* content;                  //Buffer containing file
    FILE* pFile;                    //File pointer
    long lSize;                      //File size
    HRESULT result;

    // Open file
    fopen_s(&pFile, filename, "rb");
    if (pFile == NULL) return ERROR_OPEN_FILE;

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

    // copy the file into the buffer:
    result = fread(content, 1, lSize, pFile);
    if (result != lSize) return ERROR_SIZE;

    // terminate
    fclose(pFile);

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

    //print header
    sprintf_s(hdrs,
        1024,
        "POST /upload HTTP/2\r\n"
        "Host: api.anonfile.com\r\n"
        "User-Agent: curl/7.60.0"
        "cache-control: no-cache\r\n"
        "content-type: multipart/form-data\r\n"
        "name=\"%s\"; filename=\"%s\"\r\n"
        "Content-Length: %i\r\n"
        "Accept: */*\r\n"
        "\n", nameForm, filename, lSize);

    //Open internet connection
    HINTERNET hSession = InternetOpen("WinSock", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
    if (hSession == NULL) return ERROR_INTERNET_OPEN;

    HINTERNET hConnect = InternetConnect(hSession, iaddr, INTERNET_DEFAULT_HTTP_PORT, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 1);
    if (hConnect == NULL) {
        printf("%d", GetLastError());
        return ERROR_INTERNET_CONN;
    }

    HINTERNET hRequest = HttpOpenRequest(hConnect, (const char*)"POST", url, NULL, NULL, (const char**)"*/*\0", 0, 1);
    if (hRequest == NULL) {
        printf("%d", GetLastError());
        return ERROR_INTERNET_REQ;
    } 

    BOOL sent = HttpSendRequest(hRequest, hdrs, strlen(hdrs), buffer, strlen(buffer));
    if (!sent) {
        printf("%d", GetLastError());
            return ERROR_INTERNET_SEND;
    } 

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

    return 0;
}

但不知何故,它无法执行连接:

123 
(process 7652) exited with code 14. (ERROR_INTERNET_CONN).

我错过了什么?

这里是the only anonfile file uploading example I've found,但它使用 curl 并且是 C++ 语言。

【问题讨论】:

  • InternetConnect: "如果连接成功,则返回会话的有效句柄,否则返回 NULL。要检索扩展的错误信息,请调用 GetLastError。应用程序还可以使用 InternetGetLastResponseInfo 来确定拒绝访问服务的原因。"
  • buffer 不包含任何内容。你想发送contentlSize(虽然这不能解决你的主要问题)

标签: c winapi http-post


【解决方案1】:

访问安全站点时,请更改为 RemyLebeau 提到的INTERNET_DEFAULT_HTTPS_PORT

HttpOpenRequest 中也使用INTERNET_FLAG_SECURE

使用"content-type: multipart/form-data"上传数据,需要用str_openstr_close包装数据,如下代码所示:

注意,"$$ABCXYZ$$" 是一些随机文本。将其更改为不会在目标文件中退出的更随机的内容。

int main()
{
    const char* str_header = "Content-Type: multipart/form-data; boundary=----$$ABCXYZ$$";
    const char* str_open = "------$$ABCXYZ$$\r\n"
        "Content-Disposition: form-data; name=\"file\"; filename=\"filename.txt\"\r\n"
        "Content-Type: application/octet-stream\r\n"
        "\r\n";
    const char *str_close = "\r\n------$$ABCXYZ$$--\r\n";

    FILE *fp = NULL;
    fopen_s(&fp, "filename.txt", "rb");
    if(!fp)
        return 0;

    fseek(fp, 0, SEEK_END);
    long filesize = ftell(fp);
    rewind(fp);
    int datalen = filesize + strlen(str_open) + strlen(str_close);
    char *data = malloc(datalen);

    strcpy_s(data, datalen, str_open);
    fread(data + strlen(str_open), 1, filesize, fp);
    memcpy(data + strlen(str_open) + filesize, str_close, strlen(str_close));

    HINTERNET hsession = NULL, hconnect = NULL, hrequest = NULL;

    hsession = InternetOpenA("myname", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
    if(!hsession)
        goto cleanup;

    hconnect = InternetConnectA(hsession, "api.anonfile.com",
        INTERNET_DEFAULT_HTTPS_PORT, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0);
    if(!hconnect)
        goto cleanup;

    hrequest = HttpOpenRequestA(hconnect, "POST", "/upload",
        NULL, NULL, NULL, INTERNET_FLAG_SECURE, 0);
    if(!hrequest)
        goto cleanup;

    if(!HttpSendRequestA(hrequest, str_header, (DWORD)-1, data, datalen))
        goto cleanup;

    DWORD received;
    BYTE buf[1024];
    while(InternetReadFile(hrequest, buf, sizeof(buf), &received) && received)
    {
        buf[received] = 0;
        printf("%s\n", buf);
    }

cleanup:
    fclose(fp);
    if(hsession)InternetCloseHandle(hsession);
    if(hconnect)InternetCloseHandle(hconnect);
    if(hrequest)InternetCloseHandle(hrequest);

    return 0;
}

编辑:更改 datalen,将 strlen(data) 更改为 datalen 以实现二进制文件兼容性

【讨论】:

  • 谢谢!但我在 InternetConnect() 中遇到错误,GetLastError() 函数检索值 123。我刚刚更改了fopen_s 和标题的filename 变量中的文件路径。见 pastebin.com/HreKwnN9 有什么线索吗?
  • 您是否收到任何编译警告?通过设置 Unicode 并提供错误的 ANSI 输入,我能够复制 123 错误。使用 ANSI Internet***A 函数尝试修改后的代码。
  • 就是这样!非常感谢你,伙计! :)
【解决方案2】:

您的错误消息暗示代码在 InternetConnect() 上失败。

错误代码 123 是 ERROR_INVALID_NAME:“文件名、目录名或卷标语法不正确”。

API 要求您通过 HTTPS 发布,但您尝试连接到 HTTP 端口 80 而不是 HTTPS 端口 443。

您需要将INTERNET_DEFAULT_HTTP_PORT 更改为INTERNET_DEFAULT_HTTPS_PORT

【讨论】:

    猜你喜欢
    • 2022-01-08
    • 2010-12-31
    • 1970-01-01
    • 2012-07-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-10
    • 2019-07-30
    相关资源
    最近更新 更多