cancel
Showing results for 
Search instead for 
Did you mean: 
Reply
Highlighted
Kriebb
Level: Powered On

Want to upload a file to azure devops without that the file gets corrupt (Outlook attachments to Azure Devops WorkItems)

I can upload a file to azure devops, but the file gets corrupt.

 

I can upload it from an azure function, so I do have a flow, that puts data in the azure function and that will forward it.

 

I can save the file to onedrive and open it, so it doesn't gets corrupt.

 

So, how do I proceed to make this an all-in flow? The code below is based on other stuff I found , but meanwhile, I've read that users also have difficulties with this, and use workarounds to save the file to onedrive or sharepoint and then add a shared link to the description.

 

Azure Function

#r "Newtonsoft.Json"

using System.Net;
using System.IO;
using System.Text;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Primitives;
using Newtonsoft.Json;

public static async Task<IActionResult> Run(HttpRequest req, ILogger log)
{
    log.LogInformation("C# HTTP trigger function processed a request.");

    string name = req.Query["name"];
    string workItemId = req.Query["workItemId"];

    string tokenFromDevops = @"{TOKEN}";
    string urlDevopsOrgAddAttach = @"https://dev.azure.com/{ORGNAME}/_apis/wit/attachments?api-version=5.0&fileName=";

    string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
    dynamic data = JsonConvert.DeserializeObject(requestBody);
    
    name = name ?? data?.name;
    workItemId = workItemId ?? data?.workItemId;

    string attachmentBytes = data.ContentBytes;
    string attachmentFileName = data.Name;
    var bytesFromB = Convert.FromBase64String(attachmentBytes);
    string url = urlDevopsOrgAddAttach + attachmentFileName;
    HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
    request.KeepAlive = false;
    request.Method = "POST";
    request.Headers.Add("Authorization", "Basic " + tokenFromDevops);
    request.ContentType = "application/octet-stream";
    Stream requestStream = request.GetRequestStream();
    requestStream.Write(bytesFromB, 0, bytesFromB.Length);
    requestStream.Close();

    HttpWebResponse response = (HttpWebResponse)request.GetResponse();
    var rspUploadAttachment = new StreamReader(response.GetResponseStream()).ReadToEnd();
    return rspUploadAttachment;
    
}

 

Specific action where it goes wrong: 

                                        "actions": {
                                            "AddAttachment": {
                                                "runAfter": {
                                                    "Create_file": [
                                                        "Succeeded"
                                                    ]
                                                },
                                                "metadata": {
                                                    "flowSystemMetadata": {
                                                        "swaggerOperationId": "HttpRequest"
                                                    }
                                                },
                                                "type": "ApiConnection",
                                                "inputs": {
                                                    "host": {
                                                        "connection": {
                                                            "name": "@parameters('$connections')['visualstudioteamservices']['connectionId']"
                                                        }
                                                    },
                                                    "method": "post",
                                                    "body": {
                                                        "Method": "POST",
                                                        "Uri": "/_apis/wit/attachments?api-version=5.0&areaPath=ABC+DEF&fileName=@{body('ParseAttachment')?['Name']}",
                                                        "Headers": {
                                                            "Content-Type": "application/octet-stream",
                                                            "Accept-Encoding": "gzip, deflate, br",
                                                            "Referer": "@body('Create_a_new_work_item')['fields']['Vsts_WorkItemUrl']"
                                                        },
                                                        "Body": "@{base64ToBinary(body('ParseAttachment')?['ContentBytes'])}"
                                                    },
                                                    "path": "/httprequest",
                                                    "queries": {
                                                        "account": "ab"
                                                    },
                                                    "authentication": "@parameters('$authentication')"
                                                }
                                            },

The complete Json

{
    "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
    "contentVersion": "1.0.0.0",
    "parameters": {
        "logicAppName": {
            "type": "String",
            "metadata": {
                "description": "Name of the logic app."
            }
        },
        "logicAppLocation": {
            "defaultValue": "[resourceGroup().location]",
            "allowedValues": [
                "eastasia",
                "southeastasia",
                "centralus",
                "eastus",
                "eastus2",
                "westus",
                "northcentralus",
                "southcentralus",
                "northeurope",
                "westeurope",
                "japanwest",
                "japaneast",
                "brazilsouth",
                "australiaeast",
                "australiasoutheast",
                "southindia",
                "centralindia",
                "westindia",
                "canadacentral",
                "canadaeast",
                "westcentralus",
                "westus2",
                "[resourceGroup().location]"
            ],
            "type": "String",
            "metadata": {
                "description": "Location of the logic app."
            }
        },
        "office365_Connection_Name": {
            "defaultValue": "office365",
            "type": "String",
            "metadata": {
                "description": "Name of the connection."
            }
        },
        "visualstudioteamservices_Connection_Name": {
            "defaultValue": "visualstudioteamservices",
            "type": "String",
            "metadata": {
                "description": "Name of the connection."
            }
        },
        "onedriveforbusiness_Connection_Name": {
            "defaultValue": "onedriveforbusiness",
            "type": "String",
            "metadata": {
                "description": "Name of the connection."
            }
        },
        "visualstudioteamservices_1_Connection_Name": {
            "defaultValue": "visualstudioteamservices_1",
            "type": "String",
            "metadata": {
                "description": "Name of the connection."
            }
        }
    },
    "resources": [
        {
            "type": "Microsoft.Logic/workflows",
            "name": "[parameters('logicAppName')]",
            "apiVersion": "2016-06-01",
            "location": "[parameters('logicAppLocation')]",
            "properties": {
                "state": "Disabled",
                "definition": {
                    "$schema": "https://schema.management.azure.com/providers/Microsoft.Logic/schemas/2016-06-01/workflowdefinition.json#",
                    "contentVersion": "1.0.0.0",
                    "parameters": {
                        "$connections": {
                            "defaultValue": {},
                            "type": "Object"
                        },
                        "$authentication": {
                            "defaultValue": {},
                            "type": "SecureObject"
                        }
                    },
                    "triggers": {
                        "When_a_new_email_arrives_(webhook)": {
                            "splitOn": "@triggerBody()?['value']",
                            "metadata": {
                                "flowSystemMetadata": {
                                    "swaggerOperationId": "CreateOnNewEmailSubscription"
                                },
                                "Id::AQMkAGY5NGVkYzBhLThmMWYtNDliMy1iZTQwLWY1N2EwODZkNWFmNAAuAAAD2lUV3OLUSkoAuxdneIjGTtcBAGihklHLgFNEl_e6KQIVF6YAAAKaxgAAAA==": "WorkItems"
                            },
                            "type": "ApiConnectionWebhook",
                            "inputs": {
                                "host": {
                                    "connection": {
                                        "name": "@parameters('$connections')['office365']['connectionId']"
                                    }
                                },
                                "body": {
                                    "NotificationUrl": "@{listCallbackUrl()}"
                                },
                                "path": "/MailSubscription/$subscriptions",
                                "queries": {
                                    "folderPath": "Id::AQMkAGY5NGVkYzBhLThmMWYtNDliMy1iZTQwLWY1N2EwODZkNWFmNAAuAAAD2lUV3OLUSkoAuxdneIjGTtcBAGihklHLgFNEl_e6KQIVF6YAAAKaxgAAAA==",
                                    "importance": "Any",
                                    "hasAttachment": "Any"
                                },
                                "authentication": "@parameters('$authentication')"
                            }
                        }
                    },
                    "actions": {
                        "Get_email": {
                            "runAfter": {},
                            "metadata": {
                                "flowSystemMetadata": {
                                    "swaggerOperationId": "GetEmail"
                                }
                            },
                            "type": "ApiConnection",
                            "inputs": {
                                "host": {
                                    "connection": {
                                        "name": "@parameters('$connections')['office365']['connectionId']"
                                    }
                                },
                                "method": "get",
                                "path": "/Mail/@{encodeURIComponent(triggerBody()?['Id'])}",
                                "queries": {
                                    "includeAttachments": true
                                },
                                "authentication": "@parameters('$authentication')"
                            }
                        },
                        "Apply_to_each": {
                            "foreach": "@body('Get_email')?['Attachments']",
                            "actions": {
                                "Attachment_is_in_body": {
                                    "actions": {
                                        "Img": {
                                            "runAfter": {},
                                            "type": "Compose",
                                            "inputs": "@concat('src=\\\"cid:', body('ParseAttachment')?['Name'])"
                                        },
                                        "Replacement": {
                                            "runAfter": {
                                                "Img": [
                                                    "Succeeded"
                                                ]
                                            },
                                            "type": "Compose",
                                            "inputs": "@concat(concat('src=\\\"data&colon;image/png;base64,', body('ParseAttachment')?['ContentBytes']), '\\\" data-id=\\\"')"
                                        },
                                        "ReplacedParsedBody": {
                                            "runAfter": {
                                                "Replacement": [
                                                    "Succeeded"
                                                ]
                                            },
                                            "type": "Compose",
                                            "inputs": "@replace(variables('EmailBody'), outputs('Img'), outputs('Replacement'))"
                                        },
                                        "Set_ParsedBody_(yes)": {
                                            "runAfter": {
                                                "ReplacedParsedBody": [
                                                    "Succeeded"
                                                ]
                                            },
                                            "type": "SetVariable",
                                            "inputs": {
                                                "name": "EmailBody",
                                                "value": "@{outputs('ReplacedParsedBody')}"
                                            }
                                        }
                                    },
                                    "runAfter": {
                                        "ParseAttachment": [
                                            "Succeeded"
                                        ]
                                    },
                                    "else": {
                                        "actions": {
                                            "AddAttachment": {
                                                "runAfter": {
                                                    "Create_file": [
                                                        "Succeeded"
                                                    ]
                                                },
                                                "metadata": {
                                                    "flowSystemMetadata": {
                                                        "swaggerOperationId": "HttpRequest"
                                                    }
                                                },
                                                "type": "ApiConnection",
                                                "inputs": {
                                                    "host": {
                                                        "connection": {
                                                            "name": "@parameters('$connections')['visualstudioteamservices']['connectionId']"
                                                        }
                                                    },
                                                    "method": "post",
                                                    "body": {
                                                        "Method": "POST",
                                                        "Uri": "/_apis/wit/attachments?api-version=5.0&areaPath=ABC+DEF&fileName=@{body('ParseAttachment')?['Name']}",
                                                        "Headers": {
                                                            "Content-Type": "application/octet-stream",
                                                            "Accept-Encoding": "gzip, deflate, br",
                                                            "Referer": "@body('Create_a_new_work_item')['fields']['Vsts_WorkItemUrl']"
                                                        },
                                                        "Body": "@{base64ToBinary(body('ParseAttachment')?['ContentBytes'])}"
                                                    },
                                                    "path": "/httprequest",
                                                    "queries": {
                                                        "account": "ab"
                                                    },
                                                    "authentication": "@parameters('$authentication')"
                                                }
                                            },
                                            "Update_WorkItem_with_uploaded_attachment": {
                                                "runAfter": {
                                                    "AddAttachment": [
                                                        "Succeeded"
                                                    ]
                                                },
                                                "metadata": {
                                                    "flowSystemMetadata": {
                                                        "swaggerOperationId": "HttpRequest"
                                                    }
                                                },
                                                "type": "ApiConnection",
                                                "inputs": {
                                                    "host": {
                                                        "connection": {
                                                            "name": "@parameters('$connections')['visualstudioteamservices']['connectionId']"
                                                        }
                                                    },
                                                    "method": "post",
                                                    "body": {
                                                        "Method": "PATCH",
                                                        "Uri": "/_apis/wit/workitems/@{body('Create_a_new_work_item')?['Fields']?['System_Id']}?api-version=4.1",
                                                        "Headers": {
                                                            "Content-Type": "application/json-patch+json"
                                                        },
                                                        "Body": "[\n  {\n    \"op\": \"add\",\n    \"path\": \"/relations/-\",\n    \"value\": {\n      \"rel\": \"AttachedFile\",\n      \"url\": \"@{body('AddAttachment')['url']}\",\n      \"attributes\": {\n        \"comment\": \"@{items('Apply_to_each')?['Name']}(@{body('Get_email')['Subject']})\"\n      }\n    }\n  }\n]"
                                                    },
                                                    "path": "/httprequest",
                                                    "queries": {
                                                        "account": "ab"
                                                    },
                                                    "authentication": "@parameters('$authentication')"
                                                }
                                            },
                                            "Create_file": {
                                                "runAfter": {},
                                                "metadata": {
                                                    "flowSystemMetadata": {
                                                        "swaggerOperationId": "CreateFile"
                                                    }
                                                },
                                                "type": "ApiConnection",
                                                "inputs": {
                                                    "host": {
                                                        "connection": {
                                                            "name": "@parameters('$connections')['onedriveforbusiness']['connectionId']"
                                                        }
                                                    },
                                                    "method": "post",
                                                    "body": "@base64ToBinary(items('Apply_to_each')?['ContentBytes'])",
                                                    "path": "/datasets/default/files",
                                                    "queries": {
                                                        "folderPath": "/Attachments",
                                                        "name": "@body('ParseAttachment')?['Name']"
                                                    },
                                                    "authentication": "@parameters('$authentication')"
                                                },
                                                "runtimeConfiguration": {
                                                    "contentTransfer": {
                                                        "transferMode": "Chunked"
                                                    }
                                                }
                                            }
                                        }
                                    },
                                    "expression": {
                                        "contains": [
                                            "@variables('EmailBody')",
                                            "@concat('cid:',body('ParseAttachment')?['Name'])"
                                        ]
                                    },
                                    "type": "If"
                                },
                                "ParseAttachment": {
                                    "runAfter": {},
                                    "type": "ParseJson",
                                    "inputs": {
                                        "content": "@items('Apply_to_each')",
                                        "schema": {
                                            "type": "object",
                                            "properties": {
                                                "Id": {
                                                    "type": "string"
                                                },
                                                "Name": {
                                                    "type": "string"
                                                },
                                                "ContentBytes": {
                                                    "type": "string"
                                                },
                                                "ContentType": {
                                                    "type": "string"
                                                },
                                                "Size": {
                                                    "type": "integer"
                                                }
                                            }
                                        }
                                    }
                                }
                            },
                            "runAfter": {
                                "Create_a_new_work_item": [
                                    "Succeeded"
                                ]
                            },
                            "type": "Foreach"
                        },
                        "Initialize_EmailBody": {
                            "runAfter": {
                                "Get_email": [
                                    "Succeeded"
                                ]
                            },
                            "type": "InitializeVariable",
                            "inputs": {
                                "variables": [
                                    {
                                        "name": "EmailBody",
                                        "type": "String",
                                        "value": "@{triggerBody()?['Body']}"
                                    }
                                ]
                            }
                        },
                        "Create_a_new_work_item": {
                            "runAfter": {
                                "Set_EmailBody": [
                                    "Succeeded"
                                ]
                            },
                            "metadata": {
                                "flowSystemMetadata": {
                                    "swaggerOperationId": "CreateWorkItem"
                                }
                            },
                            "type": "ApiConnection",
                            "inputs": {
                                "host": {
                                    "connection": {
                                        "name": "@parameters('$connections')['visualstudioteamservices_1']['connectionId']"
                                    }
                                },
                                "method": "patch",
                                "body": {
                                    "title": "@body('Get_email')['Subject']",
                                    "dynamicFields": {
                                        "System.AssignedTo": "somedude@somecompany.com"
                                    }
                                },
                                "path": "/@{encodeURIComponent('ABC%20DEF')}/_apis/wit/workitems/$@{encodeURIComponent('Product Backlog Item')}",
                                "queries": {
                                    "account": "ab"
                                },
                                "authentication": "@parameters('$authentication')"
                            }
                        },
                        "Update_a_work_item": {
                            "runAfter": {
                                "Apply_to_each": [
                                    "Succeeded"
                                ]
                            },
                            "metadata": {
                                "flowSystemMetadata": {
                                    "swaggerOperationId": "UpdateWorkItem"
                                }
                            },
                            "type": "ApiConnection",
                            "inputs": {
                                "host": {
                                    "connection": {
                                        "name": "@parameters('$connections')['visualstudioteamservices']['connectionId']"
                                    }
                                },
                                "method": "patch",
                                "body": {
                                    "description": "@variables('EmailBody')"
                                },
                                "path": "/_apis/wit/workitems/@{encodeURIComponent(body('Create_a_new_work_item')?['Fields']?['System_Id'])}",
                                "queries": {
                                    "account": "ab"
                                },
                                "authentication": "@parameters('$authentication')"
                            }
                        },
                        "Set_EmailBody": {
                            "runAfter": {
                                "Initialize_EmailBody": [
                                    "Succeeded"
                                ]
                            },
                            "type": "SetVariable",
                            "inputs": {
                                "name": "EmailBody",
                                "value": "@body('Get_email')?['Body']"
                            }
                        }
                    },
                    "outputs": {},
                    "description": "When an email is received on your Outlook 365, a new work item is created in the Visual Studio Team Services."
                },
                "parameters": {
                    "$connections": {
                        "value": {
                            "office365": {
                                "id": "[concat('/subscriptions/', subscription().subscriptionId, '/providers/Microsoft.Web/locations/', parameters('logicAppLocation'), '/managedApis/', 'office365')]",
                                "connectionId": "[resourceId('Microsoft.Web/connections', parameters('office365_Connection_Name'))]",
                                "connectionName": "[parameters('office365_Connection_Name')]"
                            },
                            "visualstudioteamservices": {
                                "id": "[concat('/subscriptions/', subscription().subscriptionId, '/providers/Microsoft.Web/locations/', parameters('logicAppLocation'), '/managedApis/', 'visualstudioteamservices')]",
                                "connectionId": "[resourceId('Microsoft.Web/connections', parameters('visualstudioteamservices_Connection_Name'))]",
                                "connectionName": "[parameters('visualstudioteamservices_Connection_Name')]"
                            },
                            "onedriveforbusiness": {
                                "id": "[concat('/subscriptions/', subscription().subscriptionId, '/providers/Microsoft.Web/locations/', parameters('logicAppLocation'), '/managedApis/', 'onedriveforbusiness')]",
                                "connectionId": "[resourceId('Microsoft.Web/connections', parameters('onedriveforbusiness_Connection_Name'))]",
                                "connectionName": "[parameters('onedriveforbusiness_Connection_Name')]"
                            },
                            "visualstudioteamservices_1": {
                                "id": "[concat('/subscriptions/', subscription().subscriptionId, '/providers/Microsoft.Web/locations/', parameters('logicAppLocation'), '/managedApis/', 'visualstudioteamservices_1')]",
                                "connectionId": "[resourceId('Microsoft.Web/connections', parameters('visualstudioteamservices_1_Connection_Name'))]",
                                "connectionName": "[parameters('visualstudioteamservices_1_Connection_Name')]"
                            }
                        }
                    }
                },
                "runtimeConfiguration": {
                    "lifetime": {
                        "unit": "Day",
                        "count": 30
                    },
                    "collections": {
                        "maximumItemCount": 100000
                    },
                    "performanceProfile": {
                        "throttles": {
                            "mode": "Medium"
                        }
                    }
                }
            },
            "dependsOn": [
                "[resourceId('Microsoft.Web/connections', parameters('office365_Connection_Name'))]",
                "[resourceId('Microsoft.Web/connections', parameters('visualstudioteamservices_Connection_Name'))]",
                "[resourceId('Microsoft.Web/connections', parameters('onedriveforbusiness_Connection_Name'))]",
                "[resourceId('Microsoft.Web/connections', parameters('visualstudioteamservices_1_Connection_Name'))]"
            ]
        },
        {
            "type": "Microsoft.Web/connections",
            "name": "[parameters('office365_Connection_Name')]",
            "apiVersion": "2016-06-01",
            "location": "[parameters('logicAppLocation')]",
            "properties": {
                "api": {
                    "id": "[concat('/subscriptions/', subscription().subscriptionId, '/providers/Microsoft.Web/locations/', parameters('logicAppLocation'), '/managedApis/', 'office365')]"
                },
                "displayName": "[parameters('office365_Connection_Name')]"
            }
        },
        {
            "type": "Microsoft.Web/connections",
            "name": "[parameters('visualstudioteamservices_Connection_Name')]",
            "apiVersion": "2016-06-01",
            "location": "[parameters('logicAppLocation')]",
            "properties": {
                "api": {
                    "id": "[concat('/subscriptions/', subscription().subscriptionId, '/providers/Microsoft.Web/locations/', parameters('logicAppLocation'), '/managedApis/', 'visualstudioteamservices')]"
                },
                "displayName": "[parameters('visualstudioteamservices_Connection_Name')]"
            }
        },
        {
            "type": "Microsoft.Web/connections",
            "name": "[parameters('onedriveforbusiness_Connection_Name')]",
            "apiVersion": "2016-06-01",
            "location": "[parameters('logicAppLocation')]",
            "properties": {
                "api": {
                    "id": "[concat('/subscriptions/', subscription().subscriptionId, '/providers/Microsoft.Web/locations/', parameters('logicAppLocation'), '/managedApis/', 'onedriveforbusiness')]"
                },
                "displayName": "[parameters('onedriveforbusiness_Connection_Name')]"
            }
        },
        {
            "type": "Microsoft.Web/connections",
            "name": "[parameters('visualstudioteamservices_1_Connection_Name')]",
            "apiVersion": "2016-06-01",
            "location": "[parameters('logicAppLocation')]",
            "properties": {
                "api": {
                    "id": "[concat('/subscriptions/', subscription().subscriptionId, '/providers/Microsoft.Web/locations/', parameters('logicAppLocation'), '/managedApis/', 'visualstudioteamservices_1')]"
                },
                "displayName": "[parameters('visualstudioteamservices_1_Connection_Name')]"
            }
        }
    ]
}
1 ACCEPTED SOLUTION

Accepted Solutions
Community Support Team
Community Support Team

Re: Want to upload a file to azure devops without that the file gets corrupt (Outlook attachments to Azure Devops WorkItems)

Hi @Kriebb ,

 

Uploading files to Azure DevOps is a feature that has not been supported yet. There is a similar request here could be voted at here:

https://powerusers.microsoft.com/t5/Flow-Ideas/Allow-attachments-to-be-included-when-creating-Azure-...

 

Further, here is a thread which suggests a workaround, please check it for a reference:

https://powerusers.microsoft.com/t5/Building-Flows/Create-work-item-at-Azure-DevOps-from-an-email-wi...

 

Best regards,

Mabel  

 

Community Support Team _ Mabel Mao
If this post helps, then please consider Accept it as the solution to help the other members find it more quickly.
1 REPLY 1
Community Support Team
Community Support Team

Re: Want to upload a file to azure devops without that the file gets corrupt (Outlook attachments to Azure Devops WorkItems)

Hi @Kriebb ,

 

Uploading files to Azure DevOps is a feature that has not been supported yet. There is a similar request here could be voted at here:

https://powerusers.microsoft.com/t5/Flow-Ideas/Allow-attachments-to-be-included-when-creating-Azure-...

 

Further, here is a thread which suggests a workaround, please check it for a reference:

https://powerusers.microsoft.com/t5/Building-Flows/Create-work-item-at-Azure-DevOps-from-an-email-wi...

 

Best regards,

Mabel  

 

Community Support Team _ Mabel Mao
If this post helps, then please consider Accept it as the solution to help the other members find it more quickly.

Helpful resources

Announcements
firstImage

Microsoft Business Applications Virtual Launch Event

Join us for an in-depth look at the new innovations across Dynamics 365 and the Microsoft Power Platform.

firstImage

Watch Sessions On Demand!

Continue your learning in our online communities.

Power Platform 2019 Release Wave 2 Plan

Power Platform 2019 Release Wave 2 Plan

Features releasing from October 2019 through March 2020

thirdimage

Flow Community User Group Member Badge

Fill out a quick form to claim your user group badge now!

fifthimage

Microsoft Learn

Learn how to build the business apps that you need

sixthImage

Power Platform World Tour

Find out where you can attend!

seventhimage

Webinars & Video Gallery

Watch & learn from the Flow Community Video Gallery!

Users Online
Currently online: 222 members 4,153 guests
Please welcome our newest community members: