web-dev-qa-db-ja.com

Azure関数を介して大きなファイルをアップロードする方法

Azure Functionsを探索しています。これまでにテストしたシナリオはうまく機能します。

Azure関数を使用してファイル(20MB以上)をアップロードする方法を見つけようとしているところです。

これは、Azure関数が、リクエストのストリームを取得してBLOBストレージに保存する前に、認証されたユーザーがファイルをアップロードできるかどうかを最初に検証するという考え方です。

以下は、バイトをサーバーに送信するStreamContentを作成するクライアント側のコードです。

using (Stream fileStream = ...)
{
    var streamContent = new StreamContent(fileStream);

    streamContent.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
    streamContent.Headers.ContentLength = fileStream.Length;
    streamContent.Headers.Add("FileId", fileId);

    var responseMessage = await m_httpClient.PutAsync(<validURI>, streamContent);

    responseMessage.EnsureSuccessStatusCode();

    succeeded = true;
}

サーバー側のコードは次のとおりです。

[FunctionName("upload-data")]
public static async Task<HttpResponseMessage> Run([HttpTrigger(AuthorizationLevel.Function, "put")]HttpRequestMessage req, TraceWriter log)
{
    try
    {
         //  Initialize stuff.

         //  Validate authenticated user & privileges.  

         //  Get the content stream of the request and 
         //  save it in the BLOB storage.

         return req.CreateResponse(HttpStatusCode.OK);
    }
    catch (Exception exc)
    {
        return req.CreateResponse(HttpStatusCode.InternalServerError, exc);
    }
}

メソッドの最初にブレークポイントを配置しました。ファイルのサイズに関係なく、クライアント側がリクエストを送信した直後にブレークポイントがヒットすることを期待していました。ただし、そうではありません。

Azure関数がメソッドを呼び出す前に、なんとかしてリクエストの本文のすべてのコンテンツを取得しようとしていると思います。また、基になるWebジョブの4 MBの制限を超える可能性があるファイルを送信していると思いますが、それを構成する方法がわかりませんでした。

大きなファイルをストリーミングしてAzure Functionにアップロードすることはできますか?これを機能させる方法はありますか?

13
Kzrystof

私は別のやり方を見つけました。ここに私のために働く解決策があります。

クライアントがファイルをアップロードする必要がある場合、Azure関数を呼び出して、認証(フレームワークによって提供されるIDを使用)と承認(テーブルストレージでの単純なターゲットチェックである場合があります)を実行できます。そのような操作)。

Azure関数は、特定のBlobにアクセスするために共有アクセス署名を要求します。 SASは、クライアントに書き込み専用特権でBlobストレージへのアクセスを一定期間許可します(Azureの時計のずれに注意してください)。

クライアントは、返されたSAS=を使用して、ファイルをBlobストレージに直接アップロードします。これにより、Afzaal Ahmad Zeeshanによるクライアントとの長期的な通信が回避され、全体的なコストが削減されますさらに、Azure関数はクライアントの接続速度に依存しなくなります。

8
Kzrystof

クズリストフ、あなたはここで悪い習慣に従っています。 Azure Functionsは、クライアントデバイスとの長期的な通信用ではありません。なぜ、Azure関数を管理するプログラムを作成して、意図されていないことを実行するように強制するように誘導することに、なぜ誰かが興味を持つのかわかりません。

大規模で長時間実行される関数は、予期しないタイムアウトの問題を引き起こす可能性があります。

想像してみてください。インターネット接続は良好ですが、ユーザーはそうでない可能性があります。何よりも前に注意しなければならない問題が他にもいくつかあります。そして、これは公式ドキュメント https://docs.Microsoft.com/en-us/Azure/azure-functions/functions-best-practices からの抜粋です。

このアプリケーションを設計する必要がある場合は、App Service→Azure Storage→Azure Functionsを使用します。これが私のアプリケーションのアーキテクチャのワークフローになります。

設計アプローチでは、App Serviceが画像のアップロードを処理するなど、私のアプリケーションがこの情報を順番に処理し、ユーザーがアップロードできるかどうかを指定できます。 ASP.NET Core、またはその他の言語やフレームワークを使用して、Webアプリケーションのその側を開発できます。これは、最大20MBのファイルアップロードをサポートするために簡単に昇格できることを知っています。

なぜデザインをひねるように頼んだのですか? Blob to Functionがありました。私はBlob to Functionを提案しています。

関数は、可能であればステートレスでべき等であるべきです。必要な状態情報をデータに関連付けます。たとえば、処理中の注文には、関連する州のメンバーがいる可能性があります。関数自体はステートレスのままで、関数はその状態に基づいて注文を処理できます。

関数自体はステートレスである必要があります。つまり、何も情報を保持してはならず、これを解決するには別のミドルウェア(またはfrontware)が必要になります。 Identityサーバーと通信するため、ここでApp Serviceを使用することをお勧めします。これには、ユーザーを認証するために必要な情報が含まれ、必要に応じてBlobと&rarrが最終的に機能するためです

次に、そこから出てAzure Storageに入ると、WebHooksを使用できます。または、直接のBlob Storageトリガーがそこからの委任を処理し、Azure関数でイメージを処理します—関数が必要な場合もう。 Blob Storageトリガーを使用して、さまざまな目的で関数を開始する方法を確認してください https://docs.Microsoft.com/en-us/Azure/azure-functions/functions-create-storage- blob-triggered-function

ContentLengthヘッダーを設定するとすぐに、それをストリーミングしなくなります。 PushStreamContentクラスを使用し、チャンクでストリームに書き込む必要があります。

サーバー側でチャンクとしてそのストリームに引き続きアクセスできるかどうかはわかりません。 Azure Functionsパイプラインの何かが、関数に提供する前にストリームをバッファリングする可能性があります。

1
Darrel Miller

別の解決策(ベストプラクティスではないかもしれません)は、チャンクを使用してファイルをPOSTすることです。ただし、これらのチャンクを追跡し、後で統合する必要があります。

例えば:

  • フロントエンド-複数のチャンクをエンドポイントに送信(複数のPOST)
  • バックエンド-チャンクを保存します
  • フロントエンド-送信が完了したら、エンドポイントで確認します
  • バックエンド-チャンクをマージ

Dropzone JS-Chunking

1
David Nguyen