我正在尝试使用 Azure 函数从 Blob 存储返回文件。就目前情况而言,我已经让它工作了,但是通过将整个 blob 读入内存,然后将其写回,它的工作效率很低。这适用于小文件,但一旦它们变得足够大,效率就非常低。
如何让我的函数直接返回 blob,而无需将其完全读入内存?
这是我目前正在使用的:
public static async Task<HttpResponseMessage> Run(HttpRequestMessage req, Binder binder, TraceWriter log)
{
// parse query parameter
string fileName = req.GetQueryNameValuePairs()
.FirstOrDefault(q => string.Compare(q.Key, "name", true) == 0)
.Value;
string binaryName = $"builds/{fileName}";
log.Info($"Fetching {binaryName}");
var attributes = new Attribute[]
{
new BlobAttribute(binaryName, FileAccess.Read),
new StorageAccountAttribute("vendorbuilds")
};
using (var blobStream = await binder.BindAsync<Stream>(attributes))
{
if (blobStream == null)
{
return req.CreateResponse(HttpStatusCode.NotFound);
}
using(var memoryStream = new MemoryStream())
{
blobStream.CopyTo(memoryStream);
var response = req.CreateResponse(HttpStatusCode.OK);
response.Content = new ByteArrayContent(memoryStream.ToArray());
response.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment") { FileName = fileName };
response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
return response;
}
}
}
我的function.json
文件:
{
"bindings": [
{
"authLevel": "anonymous",
"name": "req",
"type": "httpTrigger",
"direction": "in",
"methods": [
"get",
"post"
]
},
{
"name": "$return",
"type": "http",
"direction": "out"
}
],
"disabled": false
}
我不是 C# 开发人员,也不是 Azure 开发人员,所以大部分内容我都没有注意到。
最佳答案
我确实喜欢下面的最小内存占用(不将完整的 blob 保留在内存中的字节中)。请注意,我不是绑定(bind)到流,而是绑定(bind)到 ICloudBlob 实例(幸运的是,C# 函数支持 blob input binding 的多种风格)并返回开放流。使用内存分析器对其进行了测试,即使对于大 blob,它也能正常工作,没有内存泄漏。
注意:您不需要寻找流位置 0 或刷新或处置(处置将在响应结束时自动完成);
using System.IO;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Microsoft.Azure.Storage.Blob;
namespace TestFunction1
{
public static class MyFunction
{
[FunctionName("MyFunction")]
public static async Task<IActionResult> Run(
[HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = "video/{fileName}")] HttpRequest req,
[Blob("test/{fileName}", FileAccess.Read, Connection = "BlobConnection")] ICloudBlob blob,
ILogger log)
{
var blobStream = await blob.OpenReadAsync().ConfigureAwait(false);
return new FileStreamResult(blobStream, "application/octet-stream");
}
}
}
关于c# - 如何从 HTTP 触发的 Azure 函数返回 blob?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55499499/