如何将 ZIP 文件从 API 管理上传到 Blob 存储

How to upload ZIP File from API Management to Blob Storage

  1. 我正在向我的一个 Azure Api Management APIs
  2. 发送一个 POST 请求
  3. 在这个 post 请求中有一个 json 主体,其中包含 base64 编码的数据(zip 文件),如本例所示:

    { "foo": "bar", "data": "your-base64-string" }

  4. 在 API 策略中,我想向 Azure 存储 REST API 发送一个单独的请求,以将上述 base64 字符串保存为 zip 文件。

现在的问题: 我可以成功地向 Azure 存储 REST API 发送请求并通过以下语句下载生成的 zip 文件:

<set-body>@{
var base64String = (string)context.Variables.GetValueOrDefault<JObject>("body")["data"]) ;
var bytes = Convert.FromBase64String(base64String); 
var ascii = Encoding.ASCII.GetString(bytes); 
return ascii; 
}</set-body> 

问题是,我可以下载并打开 zip 文件,但由于存档已损坏,我无法提取其中的内容。

这是一个 base64 编码的 zip 文件字符串示例(包含 text.txt 的 ZIP 文件):

UEsDBBQAAAAIAL1ZxE7MTbG/EwAAABMAAAAIAAAAdGVzdC50eHQLycgsVgCiRIWS1OKStMycVD0AUEsBAh8AFAAAAAgAvVnETsxNsb8TAAAAEwAAAAgAJAAAAAAAAAAgAAAAAAAAAHRlc3QudHh0CgAgAAAAAAABABgAI8Ac2LUa1QEjwBzYtRrVAZFuI861GtUBUEsFBgAAAAABAAEAWgAAADkAAAAAAA==

这是我的代码,用于 post 发送给其他人 API:

<send-request mode="new" response-variable-name="putStorageRequest" timeout="5" ignore-error="true">
            <set-url>@((string)context.Variables["blobUrl"])</set-url>
            <set-method>PUT</set-method>
            <set-header name="x-ms-date" exists-action="override">
                <value>@((string) context.Variables["date"] )</value>
            </set-header>
            <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="Content-Type" exists-action="override">
                <value>application/zip</value>
            </set-header>
            <set-header name="Authorization" exists-action="override">
                <value>@{
                        string body = context.Request.Body.As<string>(preserveContent: true);
                        string contentType = "application/zip";
                        var base64String = (string)context.Variables.GetValueOrDefault<JObject>("body")["data"]) ;
            var bytes = Convert.FromBase64String(base64String); 
            var ascii = Encoding.ASCII.GetString(bytes)
                        var contentLength = ascii.Length;
                        var hmacSha256 = new System.Security.Cryptography.HMACSHA256 { Key = Convert.FromBase64String(context.Variables.GetValueOrDefault<string>("storageKey")) };
                        var payLoad = string.Format("{0}\n\n\n{1}\n\n{2}\n\n\n\n\n\n\nx-ms-blob-type:BlockBlob\nx-ms-date:{3}\nx-ms-version:{4}\n{5}", 
                            "PUT", 
                            contentLength,
                            contentType,
                            context.Variables["date"],
                            context.Variables["version"],
                            "/" + context.Variables.GetValueOrDefault<string>("storageAccountName") + context.Variables.GetValueOrDefault<string>("resource"));
                        return "SharedKey "+ context.Variables.GetValueOrDefault<string>("storageAccountName") + ":" + Convert.ToBase64String(hmacSha256.ComputeHash(Encoding.UTF8.GetBytes(payLoad)));
                    }</value>
            </set-header>
            <set-body>@{
                var base64String = (string)context.Variables.GetValueOrDefault<JObject>("body")["data"]) ;
                var bytes = Convert.FromBase64String(base64String); 
                var ascii = Encoding.ASCII.GetString(bytes); 
                return ascii;         
            }</set-body>
        </send-request>

Azure API Management 现在支持 body:

中的 byte[]

https://azure.microsoft.com/en-us/updates/azure-api-management-update-september-2019

The set-body policy also accepts byte array as body content.

通过在 Blob-Storage 中创建一个 zip 文件、下载它、打开 zip 文件并打开包含的文本文件,我的测试成功了。

使用了以下代码:

            <set-header name="Authorization" exists-action="override">
            <value>@{
                    string body = context.Request.Body.As<string>(preserveContent: true);
                    string contentType = "application/zip";
                    var base64String = (string)context.Variables.GetValueOrDefault<JObject>("body")["data"] ;
                    var bytes = Convert.FromBase64String(base64String); 
                    var contentLength = bytes.Length;
                    var hmacSha256 = new System.Security.Cryptography.HMACSHA256 { Key = Convert.FromBase64String(context.Variables.GetValueOrDefault<string>("storageKey")) };
                    var payLoad = string.Format("{0}\n\n\n{1}\n\n{2}\n\n\n\n\n\n\nx-ms-blob-type:BlockBlob\nx-ms-date:{3}\nx-ms-version:{4}\n{5}", 
                        "PUT", 
                        contentLength,
                        contentType,
                        context.Variables["date"],
                        context.Variables["version"],
                        "/" + context.Variables.GetValueOrDefault<string>("storageAccountName") + context.Variables.GetValueOrDefault<string>("resource"));
                    return "SharedKey "+ context.Variables.GetValueOrDefault<string>("storageAccountName") + ":" + Convert.ToBase64String(hmacSha256.ComputeHash(Encoding.UTF8.GetBytes(payLoad)));
                }</value>
        </set-header>
        <set-body>@{
            var base64String = (string)context.Variables.GetValueOrDefault<JObject>("body")["data"] ;
            var bytes = Convert.FromBase64String(base64String); 
            return bytes;         
        }</set-body>

我只需要删除:

var ascii = Encoding.ASCII.GetString(bytes);