C:通过HTTP请求将文件上传到Google云端硬盘的错误408响应

时间:2019-04-17 07:41:38

标签: c rest http curl google-drive-api

我已遵循Promise.allGoogle Tutorial通过HTTP将图像simple upload传输到Google云端硬盘,但是收到了错误404 Not Found,该错误仅在{{1 }},根据libcurl example

Google示例代码:

resumable upload

我的代码:

POST https://www.googleapis.com/upload/drive/v3/files?uploadType=media HTTP/1.1
Content-Type: image/jpeg
Content-Length: [NUMBER_OF_BYTES_IN_FILE]
Authorization: Bearer [YOUR_AUTH_TOKEN]

[JPEG_DATA]

但是我得到的回应与本教程不符。

Google表示应做出回应:

/* for storing the response */
struct MemoryStruct {
    char *memory;
    size_t size;
};

static size_t WriteMemoryCallback(void *contents, size_t size, size_t nmemb, void *userp)
{
    size_t realsize = size * nmemb;
    struct MemoryStruct *mem = (struct MemoryStruct *)userp;

    char *ptr = realloc(mem->memory, mem->size + realsize + 1);
    if(ptr == NULL) {
        /* out of memory! */
        printf("not enough memory (realloc returned NULL)\n");
        return 0;
    }
    mem->memory = ptr;
    memcpy(&(mem->memory[mem->size]), contents, realsize);
    mem->size += realsize;
    mem->memory[mem->size] = 0;

    return realsize;
}

int main(void){
    CURL *curl_handle;
    CURLcode res;

    struct MemoryStruct chunk;

    chunk.memory = malloc(1);
    chunk.size = 0;

    curl_global_init(CURL_GLOBAL_ALL);

    curl_handle = curl_easy_init();
    struct stat file_info;
    FILE *fd;

    /* get a FILE * of the image */
    fd = fopen("grinch.jpg", "rb");
    if(!fd)
        return 1;

    if(fstat(fileno(fd), &file_info) != 0)
        return 1;

    struct curl_slist *chunk = NULL;

    /* Content-Type: image/jpeg */
    chunk = curl_slist_append(chunk5, "Content-Type: image/jpeg");

    /* Content-Length: [NUMBER_OF_BYTES_IN_FILE] */
    char size[200];
    snprintf(size, 200, "Content-Length: %lld", (curl_off_t)file_info.st_size);

    chunk = curl_slist_append(chunk, size);

    /* Authorization: Bearer [YOUR_AUTH_TOKEN] */
    char auth[300];
    strcat(auth, "Authorization: Bearer ");
    strcat(auth, access_token);

    chunk = curl_slist_append(chunk, auth);

    curl_easy_setopt(curl_handle, CURLOPT_HTTPHEADER, chunk);

    /* POST https://www.googleapis.com/upload/drive/v3/files?uploadType=media */
    curl_easy_setopt(curl_handle, CURLOPT_URL, "https://www.googleapis.com/upload/drive/v3/files");

    curl_easy_setopt(curl_handle, CURLOPT_POSTFIELDS, "uploadType=media");

    /* [JPEG_DATA] */
    curl_easy_setopt(curl_handle, CURLOPT_POST, 1L);

    curl_easy_setopt(curl_handle, CURLOPT_READDATA, fd);

    curl_easy_setopt(curl_handle, CURLOPT_INFILESIZE_LARGE, (curl_off_t)file_info.st_size);

    /* Save response */
    curl_easy_setopt(curl_handle, CURLOPT_VERBOSE, 1L);

    curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, WriteMemoryCallback);

    curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, (void *)&chunk);

    curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, "libcurl-agent/1.0");

    res = curl_easy_perform(curl_handle);

    /* Print response */
    if(res != CURLE_OK) {
        fprintf(stderr, "curl_easy_perform() failed: %s\n", 
    curl_easy_strerror(res));
    }
    else {
        printf("%s\n", chunk.memory);
    }

直接在XCode中运行时得到的响应:

HTTP/1.1 200
Content-Type: application/json

{
  "name": "myObject"
}

Google Guide中找不到POST /upload/drive/v3/files HTTP/1.1 Host: www.googleapis.com User-Agent: libcurl-agent/1.0 Accept: */* Content-Type: image/jpeg Content-Length: 5123 Authorization: Bearer [my access token] * upload completely sent off: 16 out of 16 bytes < HTTP/1.1 408 Request Timeout < Content-Type: text/html; charset=UTF-8 < Referrer-Policy: no-referrer < Content-Length: 1557 < Date: Wed, 17 Apr 2019 08:32:18 GMT < Alt-Svc: quic=":443"; ma=2592000; v="46,44,43,39" < Connection: close < * Closing connection 0 <!DOCTYPE html> <html lang=en> <meta charset=utf-8> <meta name=viewport content="initial-scale=1, minimum-scale=1, width=device-width"> <title>Error 408 (Request Timeout)!!1</title> <style> *{margin:0;padding:0}html,code{font:15px/22px arial,sans-serif}html{background:#fff;color:#222;padding:15px}body{margin:7% auto 0;max-width:390px;min-height:180px;padding:30px 0 15px}* > body{background:url(//www.google.com/images/errors/robot.png) 100% 5px no-repeat;padding-right:205px}p{margin:11px 0 22px;overflow:hidden}ins{color:#777;text-decoration:none}a img{border:0}@media screen and (max-width:772px){body{background:none;margin-top:0;max-width:none;padding-right:0}}#logo{background:url(//www.google.com/images/branding/googlelogo/1x/googlelogo_color_150x54dp.png) no-repeat;margin-left:-5px}@media only screen and (min-resolution:192dpi){#logo{background:url(//www.google.com/images/branding/googlelogo/2x/googlelogo_color_150x54dp.png) no-repeat 0% 0%/100% 100%;-moz-border-image:url(//www.google.com/images/branding/googlelogo/2x/googlelogo_color_150x54dp.png) 0}}@media only screen and (-webkit-min-device-pixel-ratio:2){#logo{background:url(//www.google.com/images/branding/googlelogo/2x/googlelogo_color_150x54dp.png) no-repeat;-webkit-background-size:100% 100%}}#logo{display:inline-block;height:54px;width:150px} </style> <a href=//www.google.com/><span id=logo aria-label=Google></span></a> <p><b>408.</b> <ins>That’s an error.</ins> <p>Your client has taken too long to issue its request. <ins>That’s all we know.</ins> Program ended with exit code: 0 的解释

1 个答案:

答案 0 :(得分:1)

此:

curl_easy_setopt(curl_handle, CURLOPT_POSTFIELDS, "uploadType=media");

与以下相同:

curl_easy_setopt(curl_handle, CURLOPT_READDATA, "uploadType=media");
curl_easy_setopt(curl_handle, CURLOPT_READFUNCTION, a_fucntion_that_reads_that_string);

CURLOPT_POSTFIELDS集是POST正文。您将帖子正文设置为uploadType=media。您不想发送该字符串,而是要发送文件。字符串uploadType=media是url的一部分,您应该将其添加到url中。 Google回应为404(找不到)-网址/upload/drive/v3/files无效,应为/upload/drive/v3/files?uploadType=media

您应该设置正确的网址:

curl_easy_setopt(curl_handle, CURLOPT_URL, "https://www.googleapis.com/upload/drive/v3/files?uploadType=media");

删除

// remove
// curl_easy_setopt(curl_handle, CURLOPT_POSTFIELDS, "uploadType=media");

,然后使用FILE*CURLOPT_READDATA中读取数据。

我剩下了以下程序(对不起,一团糟):

#include <stdio.h>
#include <curl/curl.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/stat.h>

const char access_token[] = "Proceeding at three quarters impulse. Make it so, commander!";

int main() {

    CURL * curl_handle = curl_easy_init();
    struct stat file_info;
    FILE *fd;

    stat("grinch.jpg", &file_info);
    printf("%zu\n", file_info.st_size);

    /* get a FILE * of the image */
    fd = fopen("grinch.jpg", "rb");
    if (fd == NULL) {
        abort();
    }

    struct curl_slist *chunk = NULL;

    /* Content-Type: image/jpeg */
    chunk = curl_slist_append(chunk, "Content-Type: image/jpeg");

    /* Content-Length: [NUMBER_OF_BYTES_IN_FILE] */
    char size[200];
    snprintf(size, 200, "Content-Length: %lld", (long long int)file_info.st_size);

    chunk = curl_slist_append(chunk, size);

    /* Authorization: Bearer [YOUR_AUTH_TOKEN] */
    char auth[300];
    strcat(auth, "Authorization: Bearer ");
    strcat(auth, access_token);

    chunk = curl_slist_append(chunk, auth);

    curl_easy_setopt(curl_handle, CURLOPT_HTTPHEADER, chunk);
    curl_easy_setopt(curl_handle, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
    curl_easy_setopt(curl_handle, CURLOPT_URL, "https://www.googleapis.com/upload/drive/v3/files?uploadType=media");
    curl_easy_setopt(curl_handle, CURLOPT_POST, 1L);
    curl_easy_setopt(curl_handle, CURLOPT_READDATA, fd);
    curl_easy_setopt(curl_handle, CURLOPT_VERBOSE, 1L);
    CURLcode res = curl_easy_perform(curl_handle);

    /* Print response */
    if(res != CURLE_OK) {
        fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res));
    }
    else {
        printf(" SUCCESS  \n");
    }

    curl_easy_cleanup(curl_handle);
    curl_global_cleanup();

}

对于请求,我得到了响应:

{
 "error": {
  "errors": [
   {
    "domain": "global",
    "reason": "authError",
    "message": "Invalid Credentials",
    "locationType": "header",
    "location": "Authorization"
   }
  ],
  "code": 401,
  "message": "Invalid Credentials"
 }
}

但这很可能是我的凭据不正确;)。