Forum Discussion

haratsu's avatar
haratsu
Copper Contributor
Oct 13, 2023

DevOps Wiki: How to enable download of attachment

Hello,

 

I do have a git based wiki in ADO with the following structure:

| ---- REAGME.md
| ---- .attachments
       | ---- config.xml

Within README.md I want to reference config.xml in a way that:

1. enforces the file to be downloaded and not opened

2. ensures a meaningful file name proposal for the download

 

For "common" markdown this would be something like:

...
[Config](./.attachments/config.xml?download=true&name=config.xml)
...

 

unfortunately ADO performs some URL-encoding to this relative link and tries to find a file named:
- ./attachments/config.xml%3Fdownload%3Dtrue%26name%3Dconfig.xml

This file cannot be found (why should it, such a file does not exist)

 

My questions are:

1. How to properly format the relative link in ADO markdown to make the attachment downloadable

2. How to properly format the relative link in ADO markdown to define the attachments name

 

Exclusion:

- The answer "Use an absolute link like https://..../" is not an option as no-one will ever be able to maintain this across multiple branches

 

Thank you in advance 😉

6 Replies

  • I got it working, kind of. I open the files in a new tab. short answer:

        <a href="https://dev.azure.com/[PROJECT]/[ID]/_apis/git/repositories/[WIKI_REPO_ID]/Items?path=/.attachments/[filename]" target="_blank">[filename]</a>


    longer answer. I wrote this code to download all swagger contracts from several repositories, upload them as attachments and create a wiki page that links to them:

        response = await WikiHttpClient.CreateAttachmentAsync(....);
        var filename = response?.Attachment.Path.Split("/").Last();
        var path = $"{basePath}{filename}";
    
        // basepath is something like this
        // https://dev.azure.com/[PROJECT]/[ID]/_apis/git/repositories/[WIKI_REPO_ID]/Items?path=/.attachments/


    then in markdown you can link to the path:

        var sb = new StringBuilder();
        sb.AppendLine($" <a href=\"{path}\" target=\"_blank\">{displayName}</a> ");


    some downsides:

    - the filenames have to be unique and cannot be overwritten. I used the date as a suffix.
    - you'll have to clean up duplicates manually with a pull request for instance.
    - the filetypes (extensions) are limited. so i uploaded my YAML files as a text file with .txt extension

     

     

     

  • saleha15's avatar
    saleha15
    Tin Contributor

    Unfortunately, I don't think this is currently supported in Azure DevOps Git-based Wikis. Relative Markdown links are treated as file paths, so query parameters like ?download=true&name=config.xml get URL-encoded and become part of the filename, which is why the link fails.

    From what I've seen, your options are:

    • Use a standard relative link (./.attachments/config.xml), which lets users open or download the file manually depending on their browser.
    • Use an absolute URL with download parameters if you specifically need to force a download—but as you mentioned, that's difficult to maintain across branches.

    At the moment, there doesn't appear to be a built-in way to force downloads or specify a custom download filename using relative links in Azure DevOps Wiki Markdown. If anyone has found a branch-independent workaround, I'd be interested to hear it as well.

  • Hi, Azure DevOps Wiki can be a bit restrictive with attachment links because it rewrites relative paths. I do not think there is a clean wiki-native way to force download behavior like download=true for every browser. A practical workaround is to store the file somewhere with controlled download headers, or link to the raw file in the repo if that gives the behavior you need.

  • haratsu 

    ADO markdown to make an attachment downloadable

     

    [Config](./.attachments/config.xml?download=true)

     

     

    To define the attachment

     

    [Config](./.attachments/config.xml?download=true&fileName=my-config.xml)

     

    • haratsu's avatar
      haratsu
      Copper Contributor

      mohammedmubeen 

      Thanks for your reply, but as mentioned in my initial post this is what i already tried. ADO is messing up the url when using your approach resulting in the folloing error:

      {
        "$id":"1",
        "innerException":null,
        "message":"TF401174: The item 'wiki/.attachments/config.xml?download=true&fileName=config.xml' could not be found in the repository '<nonOfYourBusiness>' at the version specified by '<Branch: feature/2191 >' (resolved to commit '1dfc...bfd4')",
        "typeName":"Microsoft.TeamFoundation.Git.Server.GitItemNotFoundException, Microsoft.TeamFoundation.Git.Server",
        "typeKey":"GitItemNotFoundException",
        "errorCode":0,
        "eventId":3000
      }

       

      The reason for that - as mentioned above - is that the resulting url contains no real url parameters but encodes any char "?" or "&" as utf escaped char:

      https://.../_apis/git/repositories/.../Items?path=/wiki/.attachments/config.xml%3Fdownload%3Dtrue%26fileName%3Dconfig.xml&download=false&resolveLfs=true&%24format=octetStream&api-version=5.0-preview.1&sanitize=true&versionDescriptor.version=feature/2191