Как загрузить ZIP-файл из управления API в хранилище BLOB-объектов

  1. Я отправляю запрос POST на один из моих API управления API Azure.
  2. В этом почтовом запросе есть тело json, которое содержит данные в кодировке base64 (zip-файл), как в этом примере:

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

  3. В политике API я хочу отправить отдельный запрос в REST API службы хранилища Azure, чтобы сохранить вышеупомянутую строку base64 в виде zip-файла.

Теперь проблема: я могу успешно отправить запрос в REST API службы хранилища Azure и загрузить полученный 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-файл, но не могу извлечь его содержимое, так как архив был поврежден.

Вот пример строки zip-файла в кодировке base64 (ZIP-файл, содержащий text.txt):

UEsDBBQAAAAIAL1ZxE7MTbG/EwAAABMAAAAIAAAAdGVzdC50eHQLycgsVgCiRIWS1OKStMycVD0AUEsBAh8AFAAAAAgAvVnETsxNsb8TAAAAEwAAAAgAJAAAAAAAAAAgAAAAAAAAAHRlc3QudHh0CgAgAAAAAAABABgAI8Ac2LUa1QEjwBzYtRrVAZFuI861GtUBUEsFBgAAAAABAAEAWgAAADkAAAAAAA==

Вот мой код для публикации в Rest 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>

person Syneex    schedule 06.06.2019    source источник
comment
Не уверены, что понимаете, что хотите загрузить или скачать файл?   -  person Thomas    schedule 06.06.2019
comment
Я хочу загрузить файл с помощью REST API службы хранилища Azure. На этом этапе загрузка не требуется. Все дело в кодировке из загрузки. Надеюсь, теперь вы это понимаете!   -  person Syneex    schedule 06.06.2019
comment
Хорошо, понятно, значит, zip-файл с кодировкой base64 действителен и содержит test.txt файл с этим содержимым This is a testfile.? Проблема в том, что вы не должны преобразовывать его обратно в строку var ascii = Encoding.ASCII.GetString(bytes);. Вы должны отправить необработанные байты в api хранилища. не могли бы вы поделиться своим кодом, который выполняет загрузку?   -  person Thomas    schedule 06.06.2019
comment
Да это верно.   -  person Syneex    schedule 06.06.2019
comment
Итак, я только что загрузил код.   -  person Syneex    schedule 06.06.2019
comment
Итак, можете ли вы попробовать удалить эту строку var ascii = Encoding.ASCII.GetString(bytes) как в заголовке, так и в теле? получить contentlenght из bytes.Lenght и вернуть массив байтов для тела.   -  person Thomas    schedule 06.06.2019
comment
Так что я просто попробовал. Но проблема здесь в том, что Хранилище BLOB-объектов принимает только строки, а не массивы байтов.   -  person Syneex    schedule 06.06.2019
comment
в вашем теле вы можете попытаться вернуть поток: var bytes = Convert.FromBase64String(base64String); return new StreamContent(new MemoryStream(bytes));. Хранилище BLOB-объектов принимает файлы любого типа, фокус в том, чтобы сделать это с помощью API Management ^^   -  person Thomas    schedule 06.06.2019
comment
Да, вы уже сказали это ... Это не поддерживается в API Management ... Итак, как я могу продолжить?   -  person Syneex    schedule 06.06.2019
comment
Вы не можете справиться с этим в коде? например, нажатие на приложение-функцию?   -  person Thomas    schedule 06.06.2019
comment
Ну, я делаю это прямо сейчас, но это нечисто, если вы понимаете, о чем я. Было бы лучше обрабатывать вызов внутри API. Но если другого решения нет, другого выхода не остается. Спасибо за помощь!   -  person Syneex    schedule 06.06.2019
comment
Другим решением было бы приложение логики, поскольку оно позволяет устанавливать тела двоичных запросов. Таким образом, можно просто добавить операцию Create Blob и установить в теле следующую строку: @ base64toBinary (triggerBody () ['body'] [data ']).   -  person DSpirit    schedule 06.06.2019


Ответы (1)


Управление API Azure теперь поддерживает байт [] в теле:

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

Политика set-body также принимает массив байтов в качестве содержимого тела.

Мой тест был успешным: я создал zip-файл в Blob-Storage, загрузил его, открыл 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); 
person Markus Meyer    schedule 09.10.2019