There are multiple ways to upload a file using the Google API, as per the documentation, however, the following strategy seems to be the most useful:
- Generate a file id
- Initiate a resumable file upload with metadata (id, title, optional parent)
- Upload the actual file content
Let's go through each step and check the requests, responses and C++ code that makes it all work.
To generate an id we need to issue a GET call to this url https://www.googleapis.com/drive/v2/files/generateIds?maxResults=1
The C++ function that does this action would look like this:
CURLcode cc; curl_slist *slist = NULL; slist = curl_slist_append(slist, "Accept: text/xml"); slist = curl_slist_append(slist, "Depth: infinity"); slist = curl_slist_append(slist, "Content-Type: text/xml"); slist = curl_slist_append(slist, "Connection: Close"); slist = curl_slist_append(slist, "Authorization: Bearer <your access token string>"); CURL *pcurl = curl_easy_init(); curl_easy_setopt(pcurl, CURLOPT_VERBOSE, 1); curl_easy_setopt(pcurl, CURLOPT_URL, "https://www.googleapis.com/drive/v2/files/generateIds?maxResults=1"); curl_easy_setopt(pcurl, CURLOPT_HTTPHEADER, slist); curl_easy_setopt(pcurl, CURLOPT_HTTPAUTH, CURLAUTH_BASIC); curl_easy_setopt(pcurl, CURLOPT_WRITEFUNCTION, write_data); cc = curl_easy_perform(pcurl); if(CURLE_OK != cc){ std::cout << "Error during curl_easy_perform: " << curl_easy_strerror(cc) << std::endl; } curl_slist_free_all(slist); curl_easy_cleanup(pcurl);A successful call result will look like this:
{
"kind": "drive#generatedIds",
"ids": [
"0B2MYkjLyxeqTQ0x4czZZaWZmU2s"
],
"space": "drive"
}
The second step is to initiate a resumable upload and specify some metadata for the file id that we just generated.
CURLcode cc; std::string metadata = std::string(" { ") + "\"title\": \"myfile\"," + "\"id\": \""+ "0B2MYkjLyxeqTQ0x4czZZaWZmU2s" +"\"," + "\"parents\": [ { \"id\": \""+ "0B0jHrhwKFmtTa2dPdmVnNG4zX0U" +"\" } ]" + "} "; std::string response; std::string header; curl_slist *slist = NULL; slist = curl_slist_append(slist, "Depth: infinity"); slist = curl_slist_append(slist, "Content-Type: application/json; charset=UTF-8"); slist = curl_slist_append(slist, "Connection: Close"); slist = curl_slist_append(slist, "Authorization: Bearer <your access token string>"); slist = curl_slist_append(slist, "X-Upload-Content-Type: <mimeType of the file>"); slist = curl_slist_append(slist, "X-Upload-Content-Length: <content length in bytes>"); CURL *pcurl = curl_easy_init(); curl_easy_setopt(pcurl, CURLOPT_VERBOSE, 1); curl_easy_setopt(pcurl, CURLOPT_URL, "https://www.googleapis.com/upload/drive/v2/files?uploadType=resumable"); curl_easy_setopt(pcurl, CURLOPT_HTTPHEADER, slist); curl_easy_setopt(pcurl, CURLOPT_CUSTOMREQUEST, "POST"); curl_easy_setopt(pcurl, CURLOPT_HTTPAUTH, CURLAUTH_BASIC); curl_easy_setopt(pcurl, CURLOPT_WRITEFUNCTION, write_data); curl_easy_setopt(pcurl, CURLOPT_POSTFIELDS, metadata); curl_easy_setopt(pcurl, CURLOPT_POSTFIELDSIZE, strlen(metadata)); curl_easy_setopt(pcurl, CURLOPT_WRITEDATA, &response); curl_easy_setopt(pcurl, CURLOPT_HEADER, 1); curl_easy_setopt(pcurl, CURLOPT_HEADERDATA, &header); cc = curl_easy_perform(pcurl); if(CURLE_OK != cc){ std::cout << "Error during curl_easy_perform: " << curl_easy_strerror(cc) << std::endl; } curl_slist_free_all(slist); curl_easy_cleanup(pcurl);After this, in the response header we'll get a Location element with an url which we'll use for the actual upload.
To upload the actual file:
struct stat file_info; /* get the file size of the local file */ stat(file, &file_info); FILE* hd_src = fopen(file, "rb"); if(hd_src){ CURLcode cc; curl_slist *slist = NULL; slist = curl_slist_append(slist, "Depth: infinity"); slist = curl_slist_append(slist, "Connection: Close"); CURL *pcurl = curl_easy_init(); curl_easy_setopt(pcurl, CURLOPT_READFUNCTION, read_callback); curl_easy_setopt(pcurl, CURLOPT_UPLOAD, 1L); curl_easy_setopt(pcurl, CURLOPT_READDATA, hd_src); curl_easy_setopt(pcurl, CURLOPT_PUT, 1L); curl_easy_setopt(pcurl, CURLOPT_INFILESIZE_LARGE, (curl_off_t)file_info.st_size); curl_easy_setopt(pcurl, CURLOPT_VERBOSE, 1); curl_easy_setopt(pcurl, CURLOPT_URL, "After this call executes successfully, in the response you will get JSON metadata about the uploaded file."); curl_easy_setopt(pcurl, CURLOPT_HTTPHEADER, slist); curl_easy_setopt(pcurl, CURLOPT_HTTPAUTH, CURLAUTH_BASIC); curl_easy_setopt(pcurl, CURLOPT_WRITEFUNCTION, write_data); cc =curl_easy_perform(pcurl); if(CURLE_OK != cc){ std::cout << "Error during curl_easy_perform: " << curl_easy_strerror(cc) << std::endl; } curl_slist_free_all(slist); curl_easy_cleanup(pcurl); fclose(hd_src); }
You can check the successful upload in the Google Drive web interface. You should have a file with the name of the "title" attribute in the folder you specified, if you used a parent id, otherwise, in the root folder.
No comments:
Post a Comment