Jump to content

Featured Replies

Posted

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 by Interferon

Solved by Interferon

Go to solution
  • Author

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 by Interferon

  • Author

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);

 

  • Author

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);

 

  • Author

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 by Interferon

  • Author

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 by Interferon

  • Author

This string also failed to be recognized as a zip file:

"files[0][MyFile.zip]=HELLO"

 

  • Author
  • Solution

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 by Interferon

Recently Browsing 0

  • No registered users viewing this page.