我已遵循Promise.all
和Google 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
的解释
答案 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"
}
}
但这很可能是我的凭据不正确;)。