1
votes

I've gone through several other SO pages and while it did help me with understanding how the upload of attachments to work item works, I still cannot find a way to view the said attachment after successfully uploading it via API, especially if its an image.

APIs I've used:

To create an attachment link: https://docs.microsoft.com/en-us/rest/api/azure/devops/wit/attachments/create?view=azure-devops-server-rest-5.0

Using the attachment URL retrieved from the previous API response, I use it in the Work Item Update API, below is a snippet:

api = f"https://dev.azure.com/{organization}/_apis/wit/workitems/{work_item_id}?api-version=6.0"
    file_size = os.path.getsize(file_path)
    payload = [
        {
            "op": "add",
            "path": "/relations/-",
            "value": {
                "rel": "AttachedFile",
                "url": attachment_url,
                "attributes": {
                    "comment": "Test",
                    "resourceSize": file_size
                }
            }
        }
    ]

After this, the attachment is visible in the work item but when clicked on, it does not render the image. Instead a window opens and an infinite loading screen animation plays. Its got to be the encoding of the image thats causing this however I cannot find any documentation.

Below is the full code for uploading attachments to an existing work item.

def upload_attachment(file_path, work_item_id):

    # This part retrieves the Attachment URL
    headers = {
        "Accept": "application/json",
        "Content-Size": str(os.path.getsize(file_path)),
        "Content-Type": "application/octet-stream",
    }
    files = {'attachment': open(file_path, 'rb')}
    filename = os.path.basename(file_path)
    api = f"https://dev.azure.com/{organization}/{project}/_apis/wit/attachments?uploadType=Simple&fileName={filename}&api-version=1.0"
    resp = requests.post(url=api, files=files, headers=headers, auth=("","*fmhcstt*4nwadqy3uk*go23fga"))    
    attachment_url = resp.json()['url']

    # This part updates an existing work item, adding the attachment here.
    api = f"https://dev.azure.com/{organization}/_apis/wit/workitems/{work_item_id}?api-version=6.0"
    file_size = os.path.getsize(file_path)
    payload = [
        {
            "op": "add",
            "path": "/relations/-",
            "value": {
                "rel": "AttachedFile",
                "url": attachment_url,
                "attributes": {
                    "comment": "Test",
                    "resourceSize": file_size
                }
            }
        }
    ]
    headers = { 
        'Accept':'application/json', 
        'dataType': 'application/json-patch+json',
        'Content-type':'application/json-patch+json'
    }
    resp = requests.patch(url=api, headers=headers, json=payload, auth=("","*fmhcstt*4nwadqy3uk*go23fga"))
1
refer to this doc You could change the patch to put method. What kind of attachment are you uploading?Where is the attachment?Jeff
Sure! I'll give it a try. I'm uploading a PNG file to a work item @JeffKevinLee
Okay so before going to Chunked uploads, I tried using PUT instead of PATCH and I got an error saying the specific the HTTP method does not support PUT. Then I tried using chunked upload API and I'm getting the error as "Content-Range specified in the attachment upload request is not valid." I'm guessing that has something to do with the small file size since its only a single PNG that I'm trying to upload.KevinLee

1 Answers

1
votes

I found the issue to be with the POST request.

requests.post(url=api, files=files, headers=headers, auth=("","*fmhcstt*4nwadqy3uk*go23fga"))

Should have been:

requests.post(url=api, data=files, ...