首页 > 解决方案 > Azure API 管理重命名文件

问题描述

目前,我们有前端将文件发送到 Azure 存储帐户到特定的 blob 容器中。前端通过一个人从存储帐户获取 SAS 并将其粘贴到前端代码中,手动将 SAS 令牌放入构建中,以便它可以读取和写入存储帐户。

我们想让前端向 APIM 发送一个带有文件的请求。然后,我们要散列该文件,使用该散列作为名称并将其存储在 azure blob 存储中。我是 Azure API 管理的新手,这可能吗?好像我无法获取上传的文件。

在 APIM 策略中,我目前拥有对存储帐户的授权,但我无法弄清楚如何Request.Files像通常在 MVC 应用程序中那样获得。

我一直在查看https://docs.microsoft.com/以及https://techcommunity.microsoft.com/和 SO,我什至开始查看 Google 搜索结果的第二页。我找不到任何表明这可能与否的东西。

这是我目前的政策。它的工作原理是前端可以点击它并通过文件并保存该文件。但我们希望对文件进行哈希处理并将该哈希用作名称以避免 Azure 存储帐户 blob 容器中的名称冲突

<policies>
    <inbound>
        <base />
        <set-variable name="UTCNow" value="@(DateTime.UtcNow.ToString("R"))" />
        <set-variable name="Verb" value="@(context.Request.Method)" />
        <set-variable name="documentstorage" value="{{documentstorage}}" />
        <set-variable name="documentstoragekey" value="{{documentstorageaccesskey}}" />
        <set-variable name="version" value="2019-12-12" />
        <set-variable name="bodySize" value="@(context.Request.Headers["Content-Length"][0])" />
        <set-variable name="contentType" value="@(context.Request.Headers["Content-Type"][0])" />
        <set-header name="x-ms-version" exists-action="override">
            <value>@((string)context.Variables["version"] )</value>
        </set-header>
        <set-header name="x-ms-blob-type" exists-action="override">
            <value>BlockBlob</value>
        </set-header>
        <set-header name="date" exists-action="override">
            <value>@((string)context.Variables["UTCNow"])</value>
        </set-header>
        <set-header name="Authorization" exists-action="override">
            <value>@{
                var account = (string)context.Variables["documentstorage"];
                var key = (string)context.Variables["documentstoragekey"];
                var verb = (string)context.Variables["Verb"];
                var container = context.Request.MatchedParameters["container"];
                var fileName = context.Request.MatchedParameters["fileName"];
                var dateNow = (string)context.Variables["UTCNow"];

                string contentType = (string)context.Variables["contentType"];//"application/pdf";
 
                var contentLength = (string)context.Variables["bodySize"];
                
                var stringToSign = string.Format("{0}\n\n\n{1}\n\n{2}\n{3}\n\n\n\n\n\nx-ms-blob-type:BlockBlob\nx-ms-version:{4}\n/{5}/{6}/{7}", 
                    verb, 
                    contentLength,
                    contentType,
                    (string)context.Variables["UTCNow"],
                    (string)context.Variables["version"],
                    account,
                    container,
                    fileName);



                string signature = "";
                var unicodeKey = Convert.FromBase64String(key);
                using (var hmacSha256 = new HMACSHA256(unicodeKey))
                {
                    var dataToHmac = Encoding.UTF8.GetBytes(stringToSign);
                    signature = Convert.ToBase64String(hmacSha256.ComputeHash(dataToHmac));
                }

                var authorizationHeader = string.Format(
                        "{0} {1}:{2}",
                        "SharedKey",
                        account,
                        signature);
                

                return authorizationHeader;
            }</value>
        </set-header>
    </inbound>
    <backend>
        <base />
    </backend>
    <outbound>
        <base />
    </outbound>
    <on-error>
        <base />
    </on-error>
</policies>

标签: azurefilehttpazure-api-managementcloud-storage

解决方案


我还没有尝试过,但听起来你可以获得请求正文(我假设你的文件在哪里):

var inBody = context.Request.Body.As<byte[]>(preserveContent: true);

基于此:https ://docs.microsoft.com/en-us/azure/api-management/api-management-policy-expressions#ref-imessagebody和这个https://docs.microsoft.com/en-us /azure/api-management/api-management-transformation-policies#SetBody

但是,如果您只想获得唯一的文件名,为什么不简单地生成一个 GUID?或者你的意思是你想确保每个文件只上传一次?(然后散列可能是有意义的)


推荐阅读