Interferon Posted October 4 Posted October 4 (edited) I nearly have file uploading working using the /downloads/files end point: https://invisioncommunity.com/developers/rest-api?endpoint=downloads/files/POSTindex I am not sure how to set up the POST command, rather than the GET command. My code produces an error, but if I supply the category and other arguments in the URL, the system thinks I am trying to do a GET request. std::string token = InvisionPower::AuthenticateUser(name, password, "profile"); std::string options = "category=97&description=MyDescription&title=FileName&author=1"; nlohmann::json postData; postData = {}; postData["category"] = 97; postData["author"] = 1; postData["description"] = "Mydescription"; postData["files"].push_back({ "MyFile.zip", "MDAwMDAw" }); auto j3 = InvisionPower::APIPost("/downloads/files/", token, postData.dump()); if (j3["response"].is_string()) { Print(std::string(j3["response"])); } My code produces this error (no typo): { "errorCode": "1S303\/7", "errorMessage": "NO_CATEGEORY" } I also tried supplying the POST data this way, but it gave the same result: std::string options = "category=97&description=MyDescription&title=FileName&author=1"; auto j3 = InvisionPower::APIPost("/downloads/files/", token, options); My APIPost function looks like this: nlohmann::json APIPost(String endpoint, String bearerToken, String postData) { CURL* curl; CURLcode res; curl = curl_easy_init(); std::string readBuffer; if (curl) { std::string url = CommunityURL + "api" + endpoint; curl_easy_setopt(curl, CURLOPT_URL, url.c_str()); std::string bearerTokenHeader = "Authorization: Bearer " + bearerToken; struct curl_slist* headers = NULL; headers = curl_slist_append(headers, bearerTokenHeader.c_str()); headers = curl_slist_append(headers, "Content-Type: application/json"); // Set content type for JSON curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); // Set the POST method curl_easy_setopt(curl, CURLOPT_POST, 1L); // If there's postData, set it as the request body if (!postData.empty()) { curl_easy_setopt(curl, CURLOPT_POSTFIELDS, postData.c_str()); } curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback); curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer); res = curl_easy_perform(curl); if (res != CURLE_OK) { fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res)); } curl_easy_cleanup(curl); } String response = readBuffer; #ifdef _DEBUG Print(response); #endif auto j3 = ParseJson(response); if (j3.is_object() && j3["errorMessage"].is_string()) { Print("Error: " + std::string(j3["errorMessage"])); return {}; } return j3; } Any idea what I am doing wrong? Edited October 4 by Interferon
Interferon Posted October 4 Author Posted October 4 (edited) If I change the content-type to "application/x-www-form-urlencoded" then I get past the category and other errors, and just have a NO_FILES error: std::string options = "category=97&description=MyDescription&title=FileName&author=1"; options += "&files=MyFile.zip%2CMDAwMDAw"; auto j3 = InvisionPower::APIPost("/downloads/files/", token, options); I do not know how to encode an array in this format. The file name is "MyFile.zip" and the file contents in base64 encoding are "MDAwMDAw" (8 zeroes). Edited October 4 by Interferon
Interferon Posted October 4 Author Posted October 4 Also does not work std::string options = "category=97&description=MyDescription&title=FileName&author=1"; options += "&files=MyFile.zip=MDAwMDAw";// ??? auto j3 = InvisionPower::APIPost("/downloads/files/", token, options);
Interferon Posted October 5 Author Posted October 5 This looks correct, as far as I can tell, but it does not work: std::string options = "category=97&description=MyDescription&title=FileName&author=1"; options += "&files=" + urlEncode("[{\"MyFile.zip\":\"MDAwMDAw\"}]"); auto j3 = InvisionPower::APIPost("/downloads/files/", token, options);
Interferon Posted October 5 Author Posted October 5 (edited) I think this is closer. Now I get the error BAD_FILE_EXT: std::string options = "category=97&description=MyDescription&title=FileName&author=1&"; options += urlEncode("files[0].MyFile.zip") + "=" + urlEncode("MDAwMDAw"); auto j3 = InvisionPower::APIPost("/downloads/files/", token, options); .zip files are the only type this category accepts. Edited October 5 by Interferon
Interferon Posted October 5 Author Posted October 5 (edited) I changed the category to allow any file type, and upload works now. std::string options = "category=97&description=MyDescription&title=FileName&author=1&"; options += urlEncode("files[0].MyFile.txt") + "=" + urlEncode("Hello!"); auto j3 = InvisionPower::APIPost("/downloads/files/", token, options); The contents of the uploaded file are correct, but the file name is a long string of random characters: "files": [ { "name": "_.8193c6a2743a9ba37be5ba52574f" "url": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx, "size": 6 } ] Edited October 5 by Interferon
Interferon Posted October 5 Author Posted October 5 This string also failed to be recognized as a zip file: "files[0][MyFile.zip]=HELLO"
Solution Interferon Posted October 5 Author Solution Posted October 5 (edited) Damn, I figured it out thanks to this post: Files is NOT an array, it is an OBJECT, and the file name and contents are key-value pairs on this OBJECT. options += "files[MyFile.zip]=Hello!"; Edited October 5 by Interferon
Recommended Posts