В функции Azure я сохраняю полученные файлы. В зависимости от арендатора будет использоваться другой контейнер.
var location = Helper.GetLocation(tenant, uploadId, ...);
using (var outputStream = await binder.BindAsync<Stream>(new BlobAttribute(location , FileAccess.Write)))
{
await inputStream.CopyToAsync(outputStream);
}
Нужно ли создавать эти контейнеры заранее? (Я создаю некоторые с использованием шаблонов ARM). Мое тестирование показывает, что мне это не нужно, но я не уверен, что могу на это положиться. Если бы я мог рассчитывать на создание контейнеров для меня, мне не пришлось бы изменять шаблон ARM при добавлении нового арендатора.
Да, вы можете использовать Binder для этого. У меня есть полный пример этого на GitHub. Просто соответствующий кусок:
// We use the first char of the input file name as a dynamic part in the container. (Note: You should check if this is a valid char for the container name)
var container = $"my-dynamic-container-{inputBlobName.Substring(0,1).ToLower()}";
var attributes = new Attribute[]
{
new BlobAttribute($"{container}", FileAccess.ReadWrite),
new StorageAccountAttribute("AzureWebJobsStorage")
};
var outputContainer = await binder.BindAsync<CloudBlobContainer>(attributes);
await outputContainer.CreateIfNotExistsAsync();
Понятно. Я только что проверил это с помощью этой функции и ее выходной привязки. "myblobcontainer" не существовало заранее, и все работало нормально. контейнер получил недавно созданную среду выполнения github.com/sebader/azure-samples-collection/blob/master/…
Нужно ли создавать эти контейнеры заранее? (Я создаю некоторые, используя ARM-шаблоны). Мое тестирование показывает, что мне это не нужно, но я не уверен, что на это можно положиться.
Я думаю, вы можете положиться на это. Операция записи BlobAttribute основана на Microsoft.Azure.WebJobs.Extensions.Storage
. В этом SDK есть метод с именем CreateIfNotExistsAsync()
. Этот метод проверит, есть ли конкретный контейнер, который вы хотели, если он есть, он вернет объект контейнера, если нет, он создаст контейнер и вернет объект контейнера.
Вы можете взглянуть на эту страницу исходного кода, чтобы проверить логику:
(На самом деле, это не просто атрибут blob, многие другие службы Azure, такие как Cosmos DB, также имеют метод CreateIfNotExists, первоначальная цель которого — избежать проблем.)
При использовании метода BindAsync<Stream>
согласно исходному коду :
public Task<IBinding> BindAsync<TValue>(Attribute attribute, Attribute[] additionalAttributes = null, CancellationToken cancellationToken = default(CancellationToken))
{
ParameterInfo parameterInfo = new FakeParameterInfo(typeof(TValue), _memberInfo, attribute, additionalAttributes);
BindingProviderContext bindingProviderContext =
new BindingProviderContext(parameterInfo, bindingDataContract: null, cancellationToken: cancellationToken);
return _bindingProvider.TryCreateAsync(bindingProviderContext);
}
Он вызывает метод TryCreateAsync
. А TryCreateAsync
будет вызывать другие перегруженные методы TryCreateAsync
.
В конце концов, он вызывает этот перегруженный метод TryCreateAsync в BlobReceiptManager.cs
. И в этом методе TryCreateAsync
он проверяет, существует ли контейнер, используя bool isContainerNotFoundException = false;
. И если контейнер не существует, он будет использовать await blob.Container.CreateIfNotExistsAsync(cancellationToken);
для создания этого контейнера.
Таким образом, ответ заключается в том, что если контейнер не существует, SDK автоматически создаст его.
Но мой вопрос немного о другом. Я не делаю дополнительный вызов для создания контейнера. Я указываю местоположение большого двоичного объекта (конечно, с именем контейнера), и контейнер создается.