【问题标题】:How to upload a large file through an Azure function?如何通过 Azure 函数上传大文件?
【发布时间】:2017-09-16 13:13:14
【问题描述】:

我正在探索 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 函数? 有没有办法让这个工作?

【问题讨论】:

    标签: c# azure file-upload streaming azure-functions


    【解决方案1】:

    我找到了另一种做事方式。这是适合我的解决方案。

    当客户端需要上传文件时,调用Azure Function进行身份验证(使用框架提供的Identity)&授权(可以是在Table Storage中进行简单的针对性检查,意思是(s)he允许进行此类操作)。

    Azure 函数将要求共享访问签名以访问特定 Blob。 SAS 将授予客户端在有限时间内以只写权限访问 Blob 存储的权限(注意 Azure 上的时钟偏差)。

    然后,客户端将使用返回的 SAS 将文件直接上传到 Blob 存储。这样,它避免了 Afzaal Ahmad Zeeshan 提到的与客户端的长期通信,并进一步降低了总体成本,因为 Azure Function 不再依赖于客户端的连接速度。

    【讨论】:

      【解决方案2】:

      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 函数,我建议使用 Blob 函数,因为,

      如果可能,函数应该是无状态的和幂等的。将任何所需的状态信息与您的数据相关联。例如,正在处理的订单可能有关联的状态成员。函数可以根据该状态处理订单,而函数本身保持无状态。

      函数本身是无状态的,这意味着它们不能保存关于任何东西的任何信息,解决这个问题需要你有另一个中间件(或 frontware)来与身份服务器通信,这这就是为什么我建议在这里使用 App Service 的原因,因为它可以包含对用户进行身份验证所需的信息,然后是 Blob 和 &rarr 最后是 Function,如果需要

      然后,一旦它离开那里,进入 Azure 存储,然后我可以让 WebHooks 或直接 Blob 存储触发器从那里处理委托并在 Azure 函数中处理图像 - 如果有需要的功能了。看看如何使用 Blob 存储触发器来启动用于各种目的的函数,https://docs.microsoft.com/en-us/azure/azure-functions/functions-create-storage-blob-triggered-function

      【讨论】:

      • 与应用服务相比,Azure 功能的吸引力在于消费计划(即按使用量付费)。我了解具有长时间运行功能的问题。 Azure 函数的默认限制为 5 分钟。以 1MB/s 的速度上传 20 MB 的文件。可能需要 20 秒才能完成,这很好。关于无国籍问题,我不确定我是否在关注您。我的 Azure Function 是无状态的;这是为它提供经过身份验证的用户信息的框架,类似于应用服务正在做的事情。
      【解决方案3】:

      设置 ContentLength 标头后,您将不再流式传输它。您需要使用 PushStreamContent 类并分块写入流。

      我不知道您是否仍然可以在服务器端以块的形式访问该流。 Azure Functions 管道中的某些内容可能会在将流提供给函数之前对其进行缓冲。

      【讨论】:

      • 如果我理解正确,我必须向服务器发送请求,如果一切正常,我可以使用客户端将用来上传数据的 PushStreamContent。我会试试的!
      • 很奇怪。我查看了 HttpClientHandler 类的 PrepareAndStartContentUpload 方法。如果算法找到请求标头中指定的 ContentLength,它似​​乎会将源流实际复制到请求的流中(即不先将所有内容加载到内存中)。但是,如果在 headers 中没有指定 ContentLength,它将在将源流写入请求流之前将其复制到内存中。
      • @Kzrystof 哎呀,忘了提,您是否将 TransferEncoding 设置为分块? github.com/dotnet/corefx/blob/master/src/System.Net.Http/src/…
      【解决方案4】:

      另一种解决方案(可能不是最佳实践)是使用块发布文件。但它要求您跟踪这些块并在之后整合它们。

      例如:

      • 前端 - 将多个块发送到端点(多个 POST)
      • 后端 - 存储块
      • 前端 - 发送完成后,与端点确认
      • 后端 - 合并块

      Dropzone JS - Chunking

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-09-30
        • 2021-10-14
        • 1970-01-01
        • 2010-12-28
        • 2010-10-04
        相关资源
        最近更新 更多