Search code examples
azureattachmentwikiazure-devops-wiki

Error trying to attach an image to an Azure DevOps wiki page


I have successfully used the Azure DevOps API to create multiple wiki pages, via a standalone C# desktop app. Now I'm trying to attach an image (currently stored locally) to the wiki (as per https://learn.microsoft.com/en-us/rest/api/azure/devops/wiki/attachments/create?view=azure-devops-rest-6.0), but get an error

The wiki attachment creation failed with message : The input is not a valid Base-64 string as it contains a non-base 64 character, more than two padding characters, or an illegal character among the padding characters.

This is the code that I use to read the image file and convert it to a Base64 string - is this correct?

string base64String = null; 
string img = File.ReadAllText(att.Value); 
byte[] byteCredentials = UTF8Encoding.UTF8.GetBytes(img); 
base64String= Convert.ToBase64String(byteCredentials);

Then I create the "content" for the API call as

string data = @"{""content"": """ + base64String + @"""}";

and run the API call

string url = "https://dev.azure.com/{organization}/{project}/_apis/wiki/wikis/{wikiIdentifier}/attachments?name=Image.png&api-version=6.0";
HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest;
request.ContentType = "application/octet-stream";
request.Method = "PUT";
request.Proxy.Credentials = CredentialCache.DefaultCredentials;

request.Headers.Add("Authorization", "Basic " + Convert.ToBase64String(Encoding.ASCII.GetBytes(string.Format("{1}", "AzurePAT"))));

if (data != null)
{
     using (StreamWriter writer = new StreamWriter(request.GetRequestStream()))
     {
           writer.Write(data);
     }
}

HttpWebResponse response = request.GetResponse() as HttpWebResponse;

string result = string.Empty;
using (StreamReader reader = new StreamReader(response.GetResponseStream()))
{
     result = reader.ReadToEnd();
}

Can anyone see anything wrong with any of this? The concept of setting up a "content" JSON with an encoded Base64 string doesn't seem to be documented, so have I done it correctly?

Any help or advice gladly appreciated, thanks


Solution

  • An image file does not contain text, it is a binary file, calling File.ReadAllText probably messes up the encoding. Try:

    var img = File.ReadAllBytes(att.Value);
    var base64String = Convert.ToBase64String(img);
    

    In addition, the request expects the body to just be a string. You are passing JSON. Your code should look like this:

    using (StreamWriter writer = new StreamWriter(request.GetRequestStream()))
    {
        writer.Write(base64String);
    }